affaan-m/ECC · error · Error
Canonical session snapshot requires workers[${index}].artifa
Error message
Canonical session snapshot requires workers[${index}].artifacts to be an object What it means
worker.artifacts is missing or not a plain object. The schema only requires artifacts to be an object; its inner keys are adapter-specific (e.g. dmux uses statusFile/taskFile/handoffFile, claude-history uses sessionFile/context). This is the last per-worker guard before the loop closes.
Source
Thrown at scripts/lib/session-adapters/canonical-session.js:231
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`);
}
});
if (!isObject(snapshot.aggregates)) {
throw new Error('Canonical session snapshot requires aggregates to be an object');
}
ensureInteger(snapshot.aggregates.workerCount, 'aggregates.workerCount');
if (snapshot.aggregates.workerCount !== snapshot.workers.length) {
throw new Error('Canonical session snapshot requires aggregates.workerCount to match workers.length');
}
if (!isObject(snapshot.aggregates.states)) {
throw new Error('Canonical session snapshot requires aggregates.states to be an object');
}
if (!isObject(snapshot.aggregates.healths)) {
throw new Error('Canonical session snapshot requires aggregates.healths to be an object');View on GitHub (pinned to 01e15490f0)
Solutions
- Always emit artifacts as an object, even if empty: artifacts: {} or artifacts: { sessionFile: null }.
- Follow the established adapters: dmux maps worker.files.*, claude-history maps sessionFile:session.sessionPath.
- When no artifacts exist, use artifacts: {} rather than omitting or nulling the field.
- Pin a unit test that validates the full normalize* output for each adapter.
Example fix
// before
const worker = { id:'w1', label:'w1', state:'recorded', health:'healthy', runtime:{...}, intent:{...}, outputs:{...} };
// after
const worker = {
id:'w1', label:'w1', state:'recorded', health:'healthy', runtime:{...}, intent:{...}, outputs:{...},
artifacts: { sessionFile: session.sessionPath, context: metadata.context || null }
}; Defensive patterns
Strategy: type-guard
Validate before calling
function ensureWorkerArtifacts(worker) {
if (!worker.artifacts || typeof worker.artifacts !== 'object') {
worker.artifacts = {};
}
return worker;
} Type guard
function hasValidArtifacts(w) {
return w.artifacts !== null && typeof w.artifacts === 'object' && !Array.isArray(w.artifacts);
} Try / catch
try { validateCanonicalSnapshot(snapshot); }
catch (err) {
if (err.message.includes('.artifacts to be an object')) {
snapshot.workers.forEach(w => { if (!hasValidArtifacts(w)) ensureWorkerArtifacts(w); });
validateCanonicalSnapshot(snapshot);
} else throw err;
} Prevention
- Emit at least artifacts:{} even when no files are tracked.
- Keep per-adapter artifact keys documented and consistent.
- Add a fixture test exercising the full validate path.
When it happens
Trigger: Custom adapter omits the artifacts block entirely. Persisted recording edited to delete artifacts. Adapter sets artifacts to null when no files are present.
Common situations: New adapter for a session source that exposes no on-disk artifacts, where the author skips the field instead of emitting an empty object. Test fixtures that build a minimal worker.
Related errors
- Canonical session snapshot requires workers[${index}] to be
- Canonical session snapshot requires workers[${index}].runtim
- Canonical session snapshot requires workers[${index}].intent
- Canonical session snapshot requires workers[${index}].output
- 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/4519e427d912f10d.
Report an issue: GitHub.