affaan-m/ECC · error · Error

Canonical session snapshot requires session.sourceTarget to…

Error message

Canonical session snapshot requires session.sourceTarget to be an object

What it means

The canonical session requires a nested session.sourceTarget object describing what the session is attached to, with string fields type and value (validated immediately after). This error throws when session.sourceTarget is null, undefined, or not an object. It keeps the origin/target metadata uniformly structured for all adapters.

Solutions

  1. Populate session.sourceTarget = { type: '<type>', value: '<string>' } (e.g. { type: 'path', value: '/repo' })
  2. Regenerate the snapshot with the current normalize* adapter
  3. Migrate old snapshots: wrap a legacy flat field into the { type, value } object
  4. Check for typos like sourceTarget vs source_target

Example fix

// before
session.sourceTarget = '/worktrees/feature';
// after
session.sourceTarget = { type: 'path', value: '/worktrees/feature' };
Defensive patterns

Strategy: type-guard

Validate before calling

if (!hasSourceTarget(snap)) throw new TypeError('Missing/invalid sourceTarget');

Type guard

const hasSourceTarget = (v) => typeof v?.session?.sourceTarget === 'object' && v.session.sourceTarget !== null && typeof v.session.sourceTarget.type === 'string' && typeof v.session.sourceTarget.value === 'string';

Try / catch

try { persistCanonicalSnapshot(snap); } catch (e) { if (/sourceTarget to be an object/.test(e.message)) { snap.session.sourceTarget = { type: 'path', value: legacy }; } else throw e; }

Prevention

When it happens

Trigger: A snapshot whose session object omits sourceTarget; sourceTarget set to null or to a string like '/repo' instead of { type, value }; adapters built against an older schema where the field had a different name or flat shape.

Common situations: Old persisted snapshots predating the sourceTarget field; hand-crafted test fixtures; copying session data between adapters and dropping the nested object.

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/6f5c616e3aaf8db4. Report an issue: GitHub.

Appendix: source

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

  ensureString(snapshot.schemaVersion, 'schemaVersion');
  if (snapshot.schemaVersion !== SESSION_SCHEMA_VERSION) {
    throw new Error(`Unsupported canonical session schema version: ${snapshot.schemaVersion}`);
  }

  ensureString(snapshot.adapterId, 'adapterId');

  if (!isObject(snapshot.session)) {
    throw new Error('Canonical session snapshot requires session to be an object');
  }

  ensureString(snapshot.session.id, 'session.id');
  ensureString(snapshot.session.kind, 'session.kind');
  ensureString(snapshot.session.state, 'session.state');
  ensureOptionalString(snapshot.session.repoRoot, 'session.repoRoot');

  if (!isObject(snapshot.session.sourceTarget)) {
    throw new Error('Canonical session snapshot requires session.sourceTarget to be an object');
  }

  ensureString(snapshot.session.sourceTarget.type, 'session.sourceTarget.type');
  ensureString(snapshot.session.sourceTarget.value, 'session.sourceTarget.value');

  if (!Array.isArray(snapshot.workers)) {
    throw new Error('Canonical session snapshot requires workers to be an array');
  }

  snapshot.workers.forEach((worker, index) => {
    if (!isObject(worker)) {
      throw new Error(`Canonical session snapshot requires workers[${index}] to be an object`);
    }

    ensureString(worker.id, `workers[${index}].id`);
    ensureString(worker.label, `workers[${index}].label`);
    ensureString(worker.state, `workers[${index}].state`);
    ensureString(worker.health, `workers[${index}].health`);

View on GitHub (pinned to 8321021c54)