{"record":{"id":"3117b6f53338d528","repo":"affaan-m/ECC","slug":"canonical-session-snapshot-requires-session-to-be","errorCode":null,"errorMessage":"Canonical session snapshot requires session to be an object","messagePattern":"Canonical session snapshot requires session to be an object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/session-adapters/canonical-session.js","lineNumber":175,"sourceCode":"  }\n\n  return 'idle';\n}\n\nfunction validateCanonicalSnapshot(snapshot) {\n  if (!isObject(snapshot)) {\n    throw new Error('Canonical session snapshot must be an object');\n  }\n\n  ensureString(snapshot.schemaVersion, 'schemaVersion');\n  if (snapshot.schemaVersion !== SESSION_SCHEMA_VERSION) {\n    throw new Error(`Unsupported canonical session schema version: ${snapshot.schemaVersion}`);\n  }\n\n  ensureString(snapshot.adapterId, 'adapterId');\n\n  if (!isObject(snapshot.session)) {\n    throw new Error('Canonical session snapshot requires session to be an object');\n  }\n\n  ensureString(snapshot.session.id, 'session.id');\n  ensureString(snapshot.session.kind, 'session.kind');\n  ensureString(snapshot.session.state, 'session.state');\n  ensureOptionalString(snapshot.session.repoRoot, 'session.repoRoot');\n\n  if (!isObject(snapshot.session.sourceTarget)) {\n    throw new Error('Canonical session snapshot requires session.sourceTarget to be an object');\n  }\n\n  ensureString(snapshot.session.sourceTarget.type, 'session.sourceTarget.type');\n  ensureString(snapshot.session.sourceTarget.value, 'session.sourceTarget.value');\n\n  if (!Array.isArray(snapshot.workers)) {\n    throw new Error('Canonical session snapshot requires workers to be an array');\n  }\n","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/session-adapters/canonical-session.js#L157-L193","documentation":"After the top-level and schemaVersion checks, validateCanonicalSnapshot requires snapshot.session to be an object holding id/kind/state etc. This error throws when session is null, undefined, an array, or a non-object. The nested session record is mandatory in the canonical shape.","triggerScenarios":"Constructing a snapshot without a session key; JSON deserialization where session was null; passing only metadata like { schemaVersion, adapterId, workers }; destructuring bugs that drop the session field.","commonSituations":"Hand-built snapshots missing the nested object; adapters from older schema versions that flattened session fields to the top level; partial updates that serialized only changed top-level fields.","solutions":["Add the session object with required fields id, kind, state, repoRoot, sourceTarget","Regenerate via the matching normalize* adapter (normalizeDmuxSnapshot, normalizeOpencodeSession, etc.) instead of hand-assembling","If migrating from a flattened layout, move top-level fields into snapshot.session","Validate the JSON file you are loading actually contains a session object"],"exampleFix":"// before\n{ \"schemaVersion\": \"2.0\", \"adapterId\": \"opencode\", \"workers\": [] }\n// after\n{ \"schemaVersion\": \"2.0\", \"adapterId\": \"opencode\", \"session\": { \"id\": \"s1\", \"kind\": \"opencode\", \"state\": \"idle\", \"repoRoot\": null, \"sourceTarget\": { \"type\": \"path\", \"value\": \"/repo\" } }, \"workers\": [] }","handlingStrategy":"type-guard","validationCode":"if (!hasSessionObject(snap)) throw new TypeError('Missing session object');","typeGuard":"const hasSessionObject = (v) => typeof v?.session === 'object' && v.session !== null && !Array.isArray(v.session);","tryCatchPattern":"try { persistCanonicalSnapshot(snap); } catch (e) { if (/session to be an object/.test(e.message)) { snap = normalizeAdapter(raw); } else throw e; }","preventionTips":["Always include the session record","Use adapters to assemble snapshots"],"tags":["validation","schema","missing-field"],"backgroundTag":"schema-validation-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"}