{"record":{"id":"c54b1bf5f75c4f4e","repo":"affaan-m/ECC","slug":"canonical-session-snapshot-requires-workers-inde-c54b1b","errorCode":null,"errorMessage":"Canonical session snapshot requires workers[${index}].runtime to be an object","messagePattern":"Canonical session snapshot requires workers\\[(.+?)\\]\\.runtime to be an object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/session-adapters/canonical-session.js","lineNumber":207,"sourceCode":"\n  if (!Array.isArray(snapshot.workers)) {\n    throw new Error('Canonical session snapshot requires workers to be an array');\n  }\n\n  snapshot.workers.forEach((worker, index) => {\n    if (!isObject(worker)) {\n      throw new Error(`Canonical session snapshot requires workers[${index}] to be an object`);\n    }\n\n    ensureString(worker.id, `workers[${index}].id`);\n    ensureString(worker.label, `workers[${index}].label`);\n    ensureString(worker.state, `workers[${index}].state`);\n    ensureString(worker.health, `workers[${index}].health`);\n    ensureOptionalString(worker.branch, `workers[${index}].branch`);\n    ensureOptionalString(worker.worktree, `workers[${index}].worktree`);\n\n    if (!isObject(worker.runtime)) {\n      throw new Error(`Canonical session snapshot requires workers[${index}].runtime to be an object`);\n    }\n\n    ensureString(worker.runtime.kind, `workers[${index}].runtime.kind`);\n    ensureOptionalString(worker.runtime.command, `workers[${index}].runtime.command`);\n    ensureBoolean(worker.runtime.active, `workers[${index}].runtime.active`);\n    ensureBoolean(worker.runtime.dead, `workers[${index}].runtime.dead`);\n\n    if (!isObject(worker.intent)) {\n      throw new Error(`Canonical session snapshot requires workers[${index}].intent to be an object`);\n    }\n\n    ensureStringAllowEmpty(worker.intent.objective, `workers[${index}].intent.objective`);\n    ensureArrayOfStrings(worker.intent.seedPaths, `workers[${index}].intent.seedPaths`);\n\n    if (!isObject(worker.outputs)) {\n      throw new Error(`Canonical session snapshot requires workers[${index}].outputs to be an object`);\n    }\n","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/session-adapters/canonical-session.js#L189-L225","documentation":"validateCanonicalSnapshot throws this when a worker entry in the snapshot is missing a runtime object (or runtime is not a plain object). The canonical schema requires workers[i].runtime to carry kind (string), command (optional string), and the booleans active and dead, so renderer code can branch on process liveness without defensive checks.","triggerScenarios":"Passing a snapshot whose worker omits the runtime field entirely, sets runtime to null, or assigns a string/array instead of an object; older adapters that predate the runtime block.","commonSituations":"Schema drift between a session-recording tool that emits flat workers and the current canonical-session validator; manually constructing test snapshots without the runtime block; loading snapshots persisted by an older plugin version.","solutions":["Add a runtime object { kind, command?, active, dead } to the worker at the reported index.","Update the producing adapter to populate runtime for every worker.","Regenerate the snapshot with the current normalize*Session adapters so the runtime block is filled in.","Run validateCanonicalSnapshot on newly built snapshots in tests to catch missing runtime early."],"exampleFix":"// before\nworker.runtime = null;\n// after\nworker.runtime = { kind: 'claude', command: 'claude --resume', active: true, dead: false };","handlingStrategy":"validation","validationCode":"const runtimeOk = snapshot.workers.every(w => w && typeof w.runtime === 'object' && w.runtime !== null && typeof w.runtime.kind === 'string' && typeof w.runtime.active === 'boolean' && typeof w.runtime.dead === 'boolean');\nif (!runtimeOk) throw new Error('every worker needs a runtime { kind, active, dead }');","typeGuard":"function hasRuntime(w) { return !!w && typeof w.runtime === 'object' && w.runtime !== null && !Array.isArray(w.runtime); }","tryCatchPattern":"try { persistCanonicalSnapshot(snapshot); } catch (err) { if (String(err.message).includes('.runtime to be an object')) { console.error('Worker missing runtime block:', err.message); /* patch runtime and retry */ } else { throw err; } }","preventionTips":["Initialize runtime at worker creation: { kind, command: undefined, active: false, dead: false }.","Keep adapters in sync with the canonical schema; bump versions together.","Include snapshot fixtures in unit tests validated by validateCanonicalSnapshot.","Never hand-write snapshot JSON; use builder helpers."],"tags":["schema-validation","session-snapshot"],"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"}