affaan-m/ECC · error · Error

finalize requires --state

Error message

finalize requires --state

What it means

scripts/codex/legacy-sync-state.js implements a small state machine (begin|record|finalize|rollback) for migrating legacy Codex installs. The 'finalize' branch reads the --state flag via readFlag(argv, '--state') and throws this error when the flag is absent or has no value, because finalization needs the JSON state file created by 'begin' to know which paths to commit. The top-level require.main handler prints '[ecc-sync] ERROR: finalize requires --state' and exits 1.

Source

Thrown at scripts/codex/legacy-sync-state.js:42

    if (!codexHome || !backupDir) throw new Error('begin requires --codex-home and --backup-dir');
    process.stdout.write(`${beginLegacySyncState({
      codexHome,
      backupDir,
      previousHooksPath: readFlag(argv, '--previous-hooks-path') || '',
      installedHooksPath: readFlag(argv, '--installed-hooks-path'),
    })}\n`);
    return;
  }
  if (command === 'record') {
    const statePath = readFlag(argv, '--state');
    const filePath = readFlag(argv, '--path');
    if (!statePath || !filePath) throw new Error('record requires --state and --path');
    recordLegacySyncPath({ statePath, filePath });
    return;
  }
  if (command === 'finalize') {
    const statePath = readFlag(argv, '--state');
    if (!statePath) throw new Error('finalize requires --state');
    finalizeLegacySyncState({ statePath });
    return;
  }
  if (command === 'rollback') {
    const statePath = readFlag(argv, '--state');
    if (!statePath) throw new Error('rollback requires --state');
    const result = rollbackLegacyCodexSync({ statePath });
    process.stdout.write(`${JSON.stringify(result)}\n`);
    if (result.status !== 'rolled-back') process.exitCode = 1;
    return;
  }
  throw new Error('Usage: legacy-sync-state.js <begin|record|finalize|rollback> [options]');
}

module.exports = { main, readFlag };

if (require.main === module) {
  try {

View on GitHub (pinned to 06c5e118c4)

Solutions

  1. Re-run with the state file path produced by the earlier 'begin' step: `node scripts/codex/legacy-sync-state.js finalize --state <path-from-begin>`
  2. If you lost the path, re-run `begin` (it prints/creates the state file) and re-record paths before finalizing
  3. Run the script with no subcommand or an invalid one to see the usage line listing begin|record|finalize|rollback and their flags
  4. Check the flag spelling: it must be exactly `--state`, and it must be followed by a non-empty value

Example fix

// before
node scripts/codex/legacy-sync-state.js finalize
// after
node scripts/codex/legacy-sync-state.js finalize --state .codex-sync-state.json
Defensive patterns

Strategy: validation

Validate before calling

const stateFlag = process.argv.includes('--state') && process.argv[process.argv.indexOf('--state') + 1];
if (process.argv[2] === 'finalize' && !stateFlag) {
  console.error('finalize needs --state <path> from the begin step');
  process.exit(2);
}

Try / catch

try {
  const { main } = require('./scripts/codex/legacy-sync-state.js');
  main();
} catch (e) {
  if (/requires --state/.test(e.message)) { /* print begin's state path hint */ }
  else throw e;
}

Prevention

When it happens

Trigger: Running `node scripts/codex/legacy-sync-state.js finalize` with no --state flag; running `node scripts/codex/legacy-sync-state.js finalize --state` where --state is the last token (readFlag returns undefined for a flag with no value); misspelling the flag as `--state-file` or `--path` so the real --state is never seen.

Common situations: Operators migrating an old Codex setup run begin, then later run finalize in a fresh shell and forget the state path; copy-pasting a rollback example into a finalize command; the begin step failed earlier so no obvious state path exists to pass.

Related errors


AI-assisted analysis of affaan-m/ECC@06c5e118c4 (2026-08-18). Data as JSON: /api/errors/e20f3c2ddc3920b7. Report an issue: GitHub.