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

Thrown by validateCanonicalSnapshot when snapshot.session.sourceTarget is not a plain object. sourceTarget must carry a `type` and `value` string describing where the session originated (e.g. a repo path or socket), and is required so consumers can trace the session back to its source.

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 01e15490f0)

Solutions

  1. Always pass a sourceTarget object of shape { type: string, value: string } to normalize functions.
  2. Default sourceTarget to { type: 'unknown', value: '' } when no real source exists.
  3. Construct sourceTarget from the adapter's origin (e.g. { type: 'repo', value: repoRoot }).

Example fix

// before
normalizeClaudeHistorySession(session); // no sourceTarget -> session.sourceTarget missing

// after
normalizeClaudeHistorySession(session, { type: 'claude-history', value: session.sessionPath });
Defensive patterns

Strategy: validation

Validate before calling

// Always supply a sourceTarget to normalize functions.
const sourceTarget = { type: 'repo', value: repoRoot };
normalizeClaudeHistorySession(session, sourceTarget);

Type guard

function isSourceTarget(v) {
  return v && typeof v === 'object'
    && typeof v.type === 'string' && typeof v.value === 'string';
}

Prevention

When it happens

Trigger: A snapshot where sourceTarget is null, undefined, or a string. Common when an adapter is invoked without a source target argument, or when one was passed but not threaded into the session object.

Common situations: Calling normalizeClaudeHistorySession(session) without the second sourceTarget argument; building a snapshot by hand and forgetting sourceTarget; a refactor that dropped the parameter.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/6f5c616e3aaf8db4. Report an issue: GitHub.