affaan-m/ECC · error · Error

Legacy Codex sync state not found at ${statePath}

Error message

Legacy Codex sync state not found at ${statePath}

What it means

readState is the strict reader for the legacy Codex sync state: readRegularFileNoFollow returned null, meaning the state file does not exist at statePath, and readState turns that into an explicit error. This is the precondition-failing variant — the sibling readStateIfPresent returns null instead for first-run scenarios, so hitting this error means a code path that requires prior sync state was invoked before any state was ever created.

Source

Thrown at scripts/lib/codex-legacy-sync.js:140

        `Legacy sync path changed before removal; preserved replacement at ${quarantinePath}`
      );
    }
    throw new Error(`Legacy sync path changed before removal: ${filePath}`);
  }
  fs.unlinkSync(quarantinePath);
  fs.rmdirSync(quarantineDir);
}

function atomicWriteJson(filePath, value) {
  fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
  fs.writeFileSync(tempPath, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
  fs.renameSync(tempPath, filePath);
}

function readState(statePath) {
  const snapshot = readRegularFileNoFollow(statePath, 'utf8');
  if (!snapshot) throw new Error(`Legacy Codex sync state not found at ${statePath}`);
  return parseState(snapshot.content, statePath);
}

function readStateIfPresent(statePath) {
  const snapshot = readRegularFileNoFollow(statePath, 'utf8');
  return snapshot ? parseState(snapshot.content, statePath) : null;
}

function parseState(content, statePath) {
  const state = JSON.parse(content);
  if (state.schema !== SCHEMA || !Array.isArray(state.paths)) {
    throw new Error(`Invalid legacy Codex sync state at ${statePath}`);
  }
  return state;
}

function hasUnsafeManagedAncestor(filePath, codexHome) {
  const relativePath = path.relative(codexHome, filePath);

View on GitHub (pinned to 06c5e118c4)

Solutions

  1. Run the command that creates/initializes the legacy sync state first (the init/install sync path that uses readStateIfPresent semantics), then re-run.
  2. Verify the expected path exists afterwards: ls -l <statePath>.
  3. If the state dir was relocated, re-run setup so the state file is created at the new location.

Example fix

# before
$ ecc codex sync --prune-legacy   # no state file yet
# Error: Legacy Codex sync state not found at ...

# after
$ ecc codex sync --init-legacy      # creates state first
$ ecc codex sync --prune-legacy
Defensive patterns

Strategy: fallback

Validate before calling

import fs from 'node:fs';
function stateExists(p) { return fs.existsSync(p); }
if (!stateExists(statePath)) { /* run the initializing sync command first */ }

Type guard

function hasLegacyState(p) {
  try { return fs.lstatSync(p).isFile(); } catch { return false; }
}

Try / catch

try { state = readState(statePath); } catch (e) {
  if (/Legacy Codex sync state not found/.test(e.message)) { state = defaultState; /* first-run fallback */ }
  else throw e;
}

Prevention

When it happens

Trigger: Running a sync subcommand that updates/prunes existing legacy state (via readState) on a machine where the initial sync never ran; the state file was deleted or moved; CODEX_HOME/ECC state dir points somewhere fresh.

Common situations: New machine or container with no prior Codex legacy sync; cleanup scripts deleting the state file; a changed state directory env var.

Related errors


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