linshenkx/prompt-optimizer · error · IpcSerializationError

Failed to serialize object for IPC: ${details}

Error message

Failed to serialize object for IPC: ${details}

What it means

This error is thrown by safeSerializeForIPC when an object cannot be round-tripped through JSON (JSON.parse(JSON.stringify(obj))) before being sent over Electron IPC. Any value that JSON cannot represent — BigInt, functions, symbols, circular references, or objects with toJSON that throws — will trigger it. The wrapper exists to guarantee 100% IPC compatibility, since Electron's structured clone algorithm rejects some values that JSON accepts and vice versa.

Source

Thrown at packages/core/src/utils/ipc-serialization.ts:45

 * @returns 纯净的JavaScript对象
 */
export function safeSerializeForIPC<T>(obj: T): T {
  if (obj === null || obj === undefined) {
    return obj;
  }

  // 对于基本类型,直接返回
  if (typeof obj !== 'object') {
    return obj;
  }

  // 使用JSON序列化确保100%的IPC兼容性
  try {
    return JSON.parse(JSON.stringify(obj));
  } catch (error) {
    console.error('[IPC Serialization] Failed to serialize object:', error);
    const details = error instanceof Error ? error.message : String(error)
    throw new IpcSerializationError(`Failed to serialize object for IPC: ${details}`);
  }
}

/**
 * 检查对象是否可以安全地通过IPC传递
 * 主要用于开发时调试
 * 
 * @param obj 要检查的对象
 * @param label 对象标签,用于日志输出
 */
export function debugIPCSerializability(obj: any, label: string = 'object'): void {
  try {
    JSON.stringify(obj);
    console.log(`[IPC Debug] ${label} is serializable`);
  } catch (error) {
    console.error(`[IPC Debug] ${label} is NOT serializable:`, error);
    console.error(`[IPC Debug] Object:`, obj);
  }

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Convert BigInt fields to string before persisting: data.id = data.id.toString()
  2. Break circular references by removing back-references or using a replacer: JSON.stringify(obj, (k, v) => typeof v === 'bigint' ? v.toString() : v)
  3. Call JSON.parse(JSON.stringify(obj)) yourself in a try/catch before save/update to pinpoint which field fails
  4. If the object is a class instance, map it to a plain DTO object before passing it to save/update

Example fix

// before
await repo.save({ id: BigInt(user.id), name: user.name });

// after
await repo.save({ id: String(user.id), name: user.name });
Defensive patterns

Strategy: validation

Validate before calling

const isJsonSafe = (v: unknown): boolean => {
  try { JSON.parse(JSON.stringify(v)); return true; } catch { return false; }
};
if (!isJsonSafe(data)) {
  data = JSON.parse(JSON.stringify(data, (k, val) =>
    typeof val === 'bigint' ? val.toString() : val));
}

Type guard

const isPlainSerializable = (o: unknown): o is Record<string, unknown> =>
  o !== null && typeof o === 'object' && Object.getPrototypeOf(o) === Object.prototype;

Try / catch

try {
  await repo.save(data);
} catch (e) {
  if (e instanceof IpcSerializationError) {
    data = JSON.parse(JSON.stringify(data, (k, v) => typeof v === 'bigint' ? v.toString() : v));
    await repo.save(data);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling save, update, importAll, validateData, or importAllData with a data payload containing BigInt values (e.g. Date.now() * 1000n, IDs parsed as BigInt), circular object graphs, or class instances carrying methods/symbols that break JSON.stringify. Also triggered by objects with a custom toJSON() that itself throws.

Common situations: Storing IDs as BigInt after switching a DB driver to bigint mode; embedding a document with parent/child back-references creating cycles; passing Mongoose documents or class instances with getters that throw; using Map/Set which silently become {} and later fail downstream but never throw here unless truly non-serializable.

Related errors


AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27). Data as JSON: /api/errors/16932dc28b6c2c2c. Report an issue: GitHub.