affaan-m/ECC · error · Error
Canonical session snapshot requires workers[${index}].intent
Error message
Canonical session snapshot requires workers[${index}].intent to be an object What it means
worker.intent is missing or not a plain object. The schema requires worker.intent to hold objective (string, may be empty) and seedPaths (array of strings). This fires before those field checks, so any non-object intent is rejected outright.
Source
Thrown at scripts/lib/session-adapters/canonical-session.js:216
ensureString(worker.id, `workers[${index}].id`);
ensureString(worker.label, `workers[${index}].label`);
ensureString(worker.state, `workers[${index}].state`);
ensureString(worker.health, `workers[${index}].health`);
ensureOptionalString(worker.branch, `workers[${index}].branch`);
ensureOptionalString(worker.worktree, `workers[${index}].worktree`);
if (!isObject(worker.runtime)) {
throw new Error(`Canonical session snapshot requires workers[${index}].runtime to be an object`);
}
ensureString(worker.runtime.kind, `workers[${index}].runtime.kind`);
ensureOptionalString(worker.runtime.command, `workers[${index}].runtime.command`);
ensureBoolean(worker.runtime.active, `workers[${index}].runtime.active`);
ensureBoolean(worker.runtime.dead, `workers[${index}].runtime.dead`);
if (!isObject(worker.intent)) {
throw new Error(`Canonical session snapshot requires workers[${index}].intent to be an object`);
}
ensureStringAllowEmpty(worker.intent.objective, `workers[${index}].intent.objective`);
ensureArrayOfStrings(worker.intent.seedPaths, `workers[${index}].intent.seedPaths`);
if (!isObject(worker.outputs)) {
throw new Error(`Canonical session snapshot requires workers[${index}].outputs to be an object`);
}
ensureArrayOfStrings(worker.outputs.summary, `workers[${index}].outputs.summary`);
ensureArrayOfStrings(worker.outputs.validation, `workers[${index}].outputs.validation`);
ensureArrayOfStrings(worker.outputs.remainingRisks, `workers[${index}].outputs.remainingRisks`);
if (!isObject(worker.artifacts)) {
throw new Error(`Canonical session snapshot requires workers[${index}].artifacts to be an object`);
}
});
View on GitHub (pinned to 01e15490f0)
Solutions
- Always set worker.intent = { objective: <string>, seedPaths: <string[]> } even when empty: { objective: '', seedPaths: [] }.
- Follow normalizeClaudeHistorySession's pattern: objective from metadata title or inProgress[0], seedPaths via parseContextSeedPaths(metadata.context).
- If loading old recordings, run a migration that nests legacy worker.objective under worker.intent.objective.
- Add a fixture-based unit test that builds the minimal worker and runs validateCanonicalSnapshot to catch the omission early.
Example fix
// before
const worker = { id:'w1', label:'w1', state:'recorded', health:'healthy', runtime:{...}, outputs:{...}, artifacts:{...} };
// after
const worker = {
id:'w1', label:'w1', state:'recorded', health:'healthy', runtime:{...},
intent: { objective: metadata.title || '', seedPaths: parseContextSeedPaths(metadata.context) },
outputs:{...}, artifacts:{...}
}; Defensive patterns
Strategy: type-guard
Validate before calling
function ensureWorkerIntent(worker) {
if (!worker.intent || typeof worker.intent !== 'object') {
worker.intent = { objective: '', seedPaths: [] };
}
return worker;
} Type guard
function hasValidIntent(w) {
const i = w.intent;
return i !== null && typeof i === 'object' && !Array.isArray(i)
&& typeof i.objective === 'string' && Array.isArray(i.seedPaths);
} Try / catch
try { validateCanonicalSnapshot(snapshot); }
catch (err) {
if (err.message.includes('.intent to be an object')) {
snapshot.workers.forEach(w => { if (!hasValidIntent(w)) ensureWorkerIntent(w); });
validateCanonicalSnapshot(snapshot);
} else throw err;
} Prevention
- Always set intent:{objective:'',seedPaths:[]} as the default in worker builders.
- For claude-history, derive intent via the metadata helpers in normalizeClaudeHistorySession.
- Pin a schema test that asserts intent shape for every adapter.
When it happens
Trigger: Custom adapter constructs a worker but omits intent. Reading a persisted recording written by an adapter version that put the objective at worker.objective instead of worker.intent.objective. Hand-editing a JSON recording and removing the intent block.
Common situations: Adapting a new session source where the task objective is optional and the adapter author skips intent. Migrating snapshots between schema versions without remapping fields. Test fixtures that build minimal worker objects.
Related errors
- Canonical session snapshot requires workers[${index}] to be
- Canonical session snapshot requires workers[${index}].runtim
- Canonical session snapshot requires workers[${index}].output
- Canonical session snapshot requires workers[${index}].artifa
- Canonical session snapshot requires aggregates to be an obje
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/2a759830be7dcae6.
Report an issue: GitHub.