affaan-m/ECC · error · Error
Legacy Codex sync state not found at
Error message
Legacy Codex sync state not found at ${statePath} What it means
readState loads the legacy Codex sync state file (a JSON snapshot of files the installer manages) via a symlink-safe read. When the state file does not exist at statePath, it throws instead of returning null — unlike its sibling readStateIfPresent, which returns null for a missing file. This is an intentional hard failure: callers using readState expect an install to already be registered.
Solutions
- Run the install/registration step (beginLegacySyncState) first so the state file is created before reading it.
- If a missing state is a legitimate case, switch the caller to readStateIfPresent(statePath), which returns null instead of throwing.
- Verify statePath/codexHome is correct (echo $CODEX_HOME, check the resolved path) — a typo'd path looks identical to a missing install.
- If the state file was deleted but files exist, reinstall to regenerate a valid state snapshot rather than hand-crafting the JSON.
Example fix
// before
const state = readState(statePath); // throws if never installed
// after
const state = readStateIfPresent(statePath);
if (!state) {
// fresh machine: run install flow instead
beginLegacySyncState({ codexHome });
return;
} Defensive patterns
Strategy: fallback
Validate before calling
import fs from 'node:fs';
if (!fs.existsSync(statePath)) {
// treat as fresh install instead of calling readState
} Try / catch
let state;
try {
state = readState(statePath);
} catch (err) {
if (err instanceof Error && err.message.startsWith('Legacy Codex sync state not found')) {
state = null; // fresh machine: run install flow
} else {
throw err;
}
} Prevention
- Use readStateIfPresent when a missing state is an expected, recoverable case.
- Always run beginLegacySyncState before any command that assumes an existing install.
- Do not manually delete the sync state file; use the plugin's uninstall/cleanup flow.
- Pin CODEX_HOME explicitly in scripts/CI so reads target the same directory the install wrote to.
When it happens
Trigger: Calling readState(statePath) (directly or through the exported state accessor) when no legacy sync state file exists at statePath — e.g. before the first beginLegacySyncState was ever run, after the state file was manually deleted, or when pointing at the wrong codexHome / wrong state path.
Common situations: Running an update/rollback command that expects a prior install on a machine where the plugin was never installed; a state file removed by a cleanup script or manual `rm`; CI runners with a fresh home directory; typo'd CODEX_HOME environment variable resolving to a different directory.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Install config not found
- Invalid legacy Codex sync state at
- Refusing to replace modified legacy Codex artifact
- Refusing to reuse unsafe legacy Codex ownership path
- Agents directory not found
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/ecb5d26e2bd94904.
Report an issue: GitHub.
Appendix: 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 8321021c54)