affaan-m/ECC · error · Error

Canonical session snapshot requires workers

Error message

Canonical session snapshot requires workers[${index}].outputs to be an object

What it means

validateCanonicalSnapshot throws this when a worker has no outputs object. The canonical schema requires workers[i].outputs to contain summary, validation, and remainingRisks, each an array of strings, describing what the worker produced. Without it, consumers reading progress summaries would need null checks everywhere.

Solutions

  1. Add an outputs object with summary: [], validation: [], remainingRisks: [] (empty arrays are valid) to the worker.
  2. Ensure the worker lifecycle code initializes outputs at creation time rather than lazily.
  3. Regenerate the snapshot via the current normalize*Session adapters.
  4. Validate snapshots in CI with validateCanonicalSnapshot to catch missing outputs blocks.

Example fix

// before
worker.outputs = null;
// after
worker.outputs = { summary: [], validation: [], remainingRisks: [] };
Defensive patterns

Strategy: validation

Validate before calling

const outputsOk = snapshot.workers.every(w => w && w.outputs && typeof w.outputs === 'object' && Array.isArray(w.outputs.summary) && Array.isArray(w.outputs.validation) && Array.isArray(w.outputs.remainingRisks));
if (!outputsOk) throw new Error('every worker needs outputs { summary, validation, remainingRisks } arrays');

Type guard

function hasOutputs(w) { return !!w && typeof w.outputs === 'object' && w.outputs !== null && Array.isArray(w.outputs.summary); }

Try / catch

try { persistCanonicalSnapshot(snapshot); } catch (err) { if (String(err.message).includes('.outputs to be an object')) { console.error('Worker missing outputs block:', err.message); /* scaffold empty outputs and retry */ } else { throw err; } }

Prevention

When it happens

Trigger: Persisting or normalizing a snapshot whose worker omits outputs, sets it to null, or assigns a non-object such as an array or string.

Common situations: Workers created mid-session before any output was recorded but persisted without the empty scaffold; snapshots imported from older formats; hand-written test fixtures missing the outputs block.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/0826dcbc545992ef. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/session-adapters/canonical-session.js:223

    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`);
    }
  });

  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');

View on GitHub (pinned to 8321021c54)