{"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":"Error","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/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/state-store/queries.js#L18-L54","documentation":"stringifyJson wraps JSON.stringify for values stored in JSON columns of the state store. If serialization throws — which happens for circular references, BigInt values, or other JSON-incompatible structures — the error is rethrown with the field label and the underlying message. This keeps inserts/upserts from failing with an opaque TypeError.","triggerScenarios":"Calling insertDecision, insertGovernanceEvent, upsertInstallState, upsertWorkItem, or upsertSession with a payload containing a circular reference (e.g. an object whose parent/child link points back), a BigInt, or a function-valued field.","commonSituations":"ORM/query builder result rows that include back-references to their client; attaching a logger or config object with circular deps into a snapshot; BigInt ids from a database driver stored raw; passing a class instance with getters that reference the instance itself.","solutions":["Remove or replace the circular/non-serializable field before passing the record","Run JSON.stringify(value) yourself in a try/catch to find which label fails, then fix that field","Convert BigInt fields with Number() or String() first; strip functions via a replacer: JSON.stringify(v, (k, val) => typeof val === 'function' ? undefined : val)","For intentionally circular structures, store a flattened projection (ids only) instead of the live object graph"],"exampleFix":"// before\nupsertSession({ id, snapshot: sessionState }); // sessionState has parent back-reference\n// after\nupsertSession({ id, snapshot: JSON.parse(JSON.stringify(sessionState, (k, v) => (typeof v === 'bigint' ? String(v) : v))) });","handlingStrategy":"try-catch","validationCode":"function isJsonSafe(value, seen = new Set()) {\n  if (value === null || typeof value !== 'object') {\n    return typeof value !== 'function' && typeof value !== 'bigint';\n  }\n  if (seen.has(value)) return false;\n  seen.add(value);\n  return Object.values(value).every(v => isJsonSafe(v, seen));\n}","typeGuard":"const isJsonSafe = (v, seen = new Set()) =>\n  v === null || typeof v !== 'object'\n    ? typeof v !== 'function' && typeof v !== 'bigint'\n    : !seen.has(v) && (seen.add(v), Object.values(v).every(x => isJsonSafe(x, seen)));","tryCatchPattern":"try {\n  upsertSession(record);\n} catch (err) {\n  if (err.message.startsWith('Failed to serialize')) {\n    console.error(`Field '${err.message.match(/serialize (.*?):/)?.[1]}' is not JSON-safe`);\n    record.snapshot = JSON.parse(JSON.stringify(record.snapshot, replacer));\n    return upsertSession(record);\n  } throw err;\n}","preventionTips":["Strip functions and convert BigInt before storing objects in JSON columns","Store ids/references instead of live object graphs with back-links","Use a JSON replacer function for snapshots by convention","Test record shapes against JSON.stringify in unit tests"],"tags":["serialization","json"],"backgroundTag":"json-serialization-failed","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}