{"record":{"id":"a8f6c6421ad99d34","repo":"affaan-m/ECC","slug":"failed-to-serialize-label-error-message","errorCode":null,"errorMessage":"Failed to serialize ${label}: ${error.message}","messagePattern":"Failed to serialize (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/state-store/queries.js","lineNumber":36,"sourceCode":"    throw new Error(`Invalid limit: ${value}`);\n  }\n\n  return parsed;\n}\n\nfunction parseJsonColumn(value, fallback) {\n  if (value === null || value === undefined || value === '') {\n    return fallback;\n  }\n\n  return JSON.parse(value);\n}\n\nfunction stringifyJson(value, label) {\n  try {\n    return JSON.stringify(value);\n  } catch (error) {\n    throw new Error(`Failed to serialize ${label}: ${error.message}`);\n  }\n}\n\nfunction mapSessionRow(row) {\n  const snapshot = parseJsonColumn(row.snapshot, {});\n  return {\n    id: row.id,\n    adapterId: row.adapter_id,\n    harness: row.harness,\n    state: row.state,\n    repoRoot: row.repo_root,\n    startedAt: row.started_at,\n    endedAt: row.ended_at,\n    snapshot,\n    workerCount: Array.isArray(snapshot && snapshot.workers) ? snapshot.workers.length : 0,\n  };\n}\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/state-store/queries.js#L18-L54","documentation":"Thrown by stringifyJson() in the state-store queries module when JSON.stringify fails on a value the caller asked to write into a JSON column. The try/catch wraps the native call so the surfaced error names the column label rather than reporting a bare 'Converting circular structure to JSON'. The helper is used to serialize snapshots and other structured fields before they go into SQLite.","triggerScenarios":"Passing an object with a circular reference (e.g. a session object that references itself, a DOM-like node, or an object that includes its parent); passing a value containing a BigInt (JSON.stringify throws on BigInt by default); passing a value with a .toJSON() that itself throws.","commonSituations":"Storing a session snapshot that inadvertently includes the parent session record; serializing a worker plan whose templateVariables reference the plan object; mixing BigInt row IDs into a JSON payload after a migration to bigint; a custom class whose toJSON override errors on missing fields.","solutions":["Strip circular references before persisting: build a fresh plain object picking only the fields you need.","Convert BigInt values to String or Number before serializing, or use a replacer: JSON.stringify(value, (_, v) => typeof v === 'bigint' ? v.toString() : v).","Use util.inspect or a safe-stringify library to detect circular structure at debug time, then fix the source shape.","Unit-test the serialization path with a representative payload so the failure surfaces before it reaches the DB writer."],"exampleFix":"// before\nstringifyJson(sessionWithCircularRef, 'snapshot');\n// -> Failed to serialize snapshot: Converting circular structure to JSON\n\n// after\nconst { snapshot } = sessionWithCircularRef;\nconst safeSnapshot = {\n  workers: (snapshot.workers || []).map(({ name, status, branch }) => ({ name, status, branch })),\n};\nstringifyJson(safeSnapshot, 'snapshot');","handlingStrategy":"try-catch","validationCode":"function isSafeJson(value) {\n  try {\n    JSON.stringify(value);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nif (!isSafeJson(snapshot)) {\n  // strip known circular fields or build a plain-object copy\n  snapshot = { workers: snapshot.workers.map(w => ({ name: w.name, status: w.status })) };\n}\nstringifyJson(snapshot, 'snapshot');","typeGuard":"function isPlainSerializable(value, seen = new WeakSet()) {\n  if (value === null || typeof value !== 'object') return true;\n  if (typeof value === 'function' || typeof value === 'bigint') return false;\n  if (seen.has(value)) return false;\n  seen.add(value);\n  return Object.values(value).every(v => isPlainSerializable(v, seen));\n}","tryCatchPattern":"try {\n  stringifyJson(value, label);\n} catch (error) {\n  if (/Failed to serialize/.test(error.message)) {\n    // fall back to a safe replacer or drop the field\n    return JSON.stringify(value, (_, v) => typeof v === 'bigint' ? v.toString() : v);\n  }\n  throw error;\n}","preventionTips":["Never persist objects that reference their parent — build a fresh snapshot object.","Convert BigInt IDs to String before they enter the snapshot path.","Add a unit test that JSON.stringify's every payload shape you persist.","Use a WeakSet-based cycle detector in dev builds to surface cycles early."],"tags":["state-store","serialization","json","circular-reference"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}