affaan-m/ECC · error · Error

--from is required for handoffs.

Error message

--from is required for handoffs.

What it means

Thrown by runWriteCommand in scripts/memory.js when the `handoff` subcommand is invoked without the `--from` flag. The memory CLI requires every handoff to declare its source harness so the resulting memory record is attributable. Without it the write is rejected before any file is touched.

Source

Thrown at scripts/memory.js:416

    throw new Error(
      `memory ${command} is disabled in dry-run mode; no files were written.`
    );
  }
}

function runInitCommand({ command, options, positionals, roots }) {
  requireNoPositionals(positionals, command);
  return printInit(
    initializeVault({ roots, scopes: options.scopes || undefined }),
    options.json
  );
}

function runWriteCommand({ command, options, positionals, roots }) {
  requireNoPositionals(positionals, command);
  if (!options.title) throw new Error('--title is required.');
  if (command === 'handoff' && !options.from) {
    throw new Error('--from is required for handoffs.');
  }
  if (command === 'handoff' && (!options.targets || options.targets.length === 0)) {
    throw new Error('At least one --target is required for handoffs.');
  }
  return printWrite(
    saveMemory(saveInput(options, command === 'handoff' ? 'handoff' : null), { roots }),
    options.json
  );
}

function runSearchCommand({ options, positionals, roots }) {
  const query = positionals.join(' ');
  return printSearch(query, searchMemories(query, {
    roots,
    scopes: options.scopes,
    kinds: options.kinds,
    targetHarness: options.targetHarness,
    limit: options.limit,

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Add `--from <harness-name>` (e.g. `--from claude`) to the handoff invocation.
  2. Set the ECC_MEMORY_HARNESS environment variable as a fallback only if you intentionally want the `save` semantics — but note `handoff` still requires the explicit flag.
  3. If scripting, assert the flag is non-empty before spawning the CLI to surface the error at the call site.

Example fix

// before
node scripts/memory.js handoff --title "Sync context" --target claude
// after
node scripts/memory.js handoff --from codex --title "Sync context" --target claude
Defensive patterns

Strategy: validation

Validate before calling

function buildHandoffArgs({ from, title, targets }) {
  if (!from || typeof from !== 'string') {
    throw new Error('handoff requires a non-empty --from harness name');
  }
  if (!Array.isArray(targets) || targets.length === 0) {
    throw new Error('handoff requires at least one --target harness');
  }
  if (!title) throw new Error('handoff requires --title');
  return ['handoff', '--from', from, '--title', title, ...targets.flatMap(t => ['--target', t])];
}

Type guard

function isHandoffInput(value) {
  return (
    value !== null &&
    typeof value === 'object' &&
    typeof value.from === 'string' && value.from.length > 0 &&
    typeof value.title === 'string' && value.title.length > 0 &&
    Array.isArray(value.targets) && value.targets.every(t => typeof t === 'string' && t.length > 0)
  );
}

Prevention

When it happens

Trigger: Running `node scripts/memory.js handoff --title "X" --target claude` while omitting `--from`. Also triggered when `--from` is set to an empty string, since the guard is a falsy check (`!options.from`) rather than a length check. The `save` subcommand does NOT require `--from` (it falls back to ECC_MEMORY_HARNESS env or 'unknown') — only `handoff` does.

Common situations: An agent or script wires up a handoff invocation and forgets the source harness flag; relying on the `save` command's fallback behavior and assuming `handoff` behaves the same; passing `--from=` with no value through a shell that swallows the empty token.

Related errors


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