affaan-m/ECC · error · Error
Refusing to replace modified legacy Codex artifact: ${filePa
Error message
Refusing to replace modified legacy Codex artifact: ${filePath} What it means
While verifying prior install state, assertInstalledStateUnmodified() hits an entry whose installedSha256 is null — the path was recorded as absent (a tombstone for a file ECC intended to create) — but readRegularFileNoFollow() now finds a regular file there. Because ECC never wrote that file, overwriting it could destroy user data, so the reinstall is refused.
Source
Thrown at scripts/lib/codex-legacy-sync.js:212
return {
path: filePath,
installedSha256: null,
previousType,
previousContentBase64: snapshot ? snapshot.content.toString('base64') : null,
previousMode: snapshot ? snapshot.mode : null,
};
}
function assertInstalledStateUnmodified(state) {
for (const entry of state.paths) {
const filePath = path.resolve(entry.path);
const trustedRoot = getTrustedRoot(state, filePath);
if (!trustedRoot || hasUnsafeManagedAncestor(filePath, trustedRoot)) {
throw new Error(`Refusing to reuse unsafe legacy Codex ownership path: ${filePath}`);
}
const snapshot = readRegularFileNoFollow(filePath);
if (!entry.installedSha256) {
if (snapshot) throw new Error(`Refusing to replace modified legacy Codex artifact: ${filePath}`);
continue;
}
const digest = snapshot
? crypto.createHash('sha256').update(snapshot.content).digest('hex')
: null;
if (digest !== entry.installedSha256) {
throw new Error(`Refusing to replace modified legacy Codex artifact: ${filePath}`);
}
}
}
function beginLegacySyncState(options) {
const codexHome = path.resolve(options.codexHome);
const statePath = getStatePath(codexHome);
const configPath = path.join(codexHome, 'config.toml');
const agentsPath = path.join(codexHome, 'AGENTS.md');
const installedHooksPath = options.installedHooksPath ? path.resolve(options.installedHooksPath) : null;
const priorState = readStateIfPresent(statePath);View on GitHub (pinned to 06c5e118c4)
Solutions
- Inspect the file named in the error; if it is disposable or yours, move it aside and re-run the sync
- If it must be kept, copy its content elsewhere, let ECC manage the path, then merge manually
- If the whole install state is stale, back up and delete the sync-state file to start fresh
Example fix
# before: retry throws Refusing to replace modified legacy Codex artifact: /home/u/.codex/config.toml mv ~/.codex/config.toml ~/.codex/config.toml.pre-ecc # after: re-run the legacy Codex sync, then merge your config back if needed
Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs'), path = require('path');
const conflicts = state.paths
.filter(e => !e.installedSha256)
.filter(e => fs.existsSync(path.resolve(e.path)));
if (conflicts.length) reportFileConflicts(conflicts); // resolve before re-running the sync Try / catch
try { beginLegacySyncState({ codexHome }); }
catch (err) {
if (/Refusing to replace modified legacy Codex artifact/.test(err.message)) {
// the message contains the path: move the unexpected file aside, then retry
} else throw err;
} Prevention
- Do not create files in CODEX_HOME while a sync is pending
- Complete or roll back interrupted installs before letting other tooling run
- Treat paths in the state file as reserved by ECC
When it happens
Trigger: A first sync recorded paths it planned to create and was interrupted before installing them; before the retry, someone (user, other tool, other agent) created a file at one of those paths, e.g. ~/.codex/config.toml now exists where the entry expected absence.
Common situations: User runs 'codex' login/config between a failed ECC install and the retry; dotfile managers or parallel agents writing into CODEX_HOME concurrently.
Related errors
- Legacy Codex sync state requires recovery before reinstall:
- Invalid ${flag}: expected a single cache path segment
- Unknown argument: ${arg}
- Missing value for ${arg}
- Failed to read ${filePath}: ${error.message}
AI-assisted analysis of affaan-m/ECC@06c5e118c4 (2026-08-18).
Data as JSON: /api/errors/2a6e1cd684bd4bbe.
Report an issue: GitHub.