{"record":{"id":"8921a5bb281ea6b0","repo":"affaan-m/ECC","slug":"legacy-sync-path-changed-before-removal-filepat","errorCode":null,"errorMessage":"Legacy sync path changed before removal: ${filePath}","messagePattern":"Legacy sync path changed before removal: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"scripts/lib/codex-legacy-sync.js","lineNumber":125,"sourceCode":"  const quarantinePath = path.join(quarantineDir, path.basename(filePath));\n  fs.renameSync(filePath, quarantinePath);\n  const quarantined = openRegularFileNoFollow(quarantinePath);\n  const openedStat = fs.fstatSync(opened.descriptor, { bigint: true });\n  const quarantinedStat = fs.fstatSync(quarantined.descriptor, { bigint: true });\n  fs.closeSync(quarantined.descriptor);\n  fs.closeSync(opened.descriptor);\n  opened.descriptor = null;\n  if (quarantinedStat.dev !== openedStat.dev || quarantinedStat.ino !== openedStat.ino) {\n    try {\n      fs.linkSync(quarantinePath, filePath);\n      fs.unlinkSync(quarantinePath);\n      fs.rmdirSync(quarantineDir);\n    } catch (_restoreError) {\n      throw new Error(\n        `Legacy sync path changed before removal; preserved replacement at ${quarantinePath}`\n      );\n    }\n    throw new Error(`Legacy sync path changed before removal: ${filePath}`);\n  }\n  fs.unlinkSync(quarantinePath);\n  fs.rmdirSync(quarantineDir);\n}\n\nfunction atomicWriteJson(filePath, value) {\n  fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });\n  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;\n  fs.writeFileSync(tempPath, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600 });\n  fs.renameSync(tempPath, filePath);\n}\n\nfunction readState(statePath) {\n  const snapshot = readRegularFileNoFollow(statePath, 'utf8');\n  if (!snapshot) throw new Error(`Legacy Codex sync state not found at ${statePath}`);\n  return parseState(snapshot.content, statePath);\n}\n","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/affaan-m/ECC/blob/06c5e118c4d3e6c3b7f9445f973a2194c82de193/scripts/lib/codex-legacy-sync.js#L107-L143","documentation":"The same quarantine identity check as error 97, but the better outcome: dev/ino of the opened file and its quarantined copy differ (the path was swapped after open), and the restore succeeded — the original content was linked back to the path, the quarantine removed, and the operation aborted cleanly. The throw exists so callers know the removal did NOT happen and the file that raced in was discarded safely.","triggerScenarios":"A concurrent process renames/replaces the state file between the open() and the unlink() phases of removeOpenedRegularFile, in a directory where the restore link can succeed.","commonSituations":"Two `ecc codex sync` runs (or a sync plus a state-rewriting tool) operating on the same legacy state path at the same moment.","solutions":["Simply re-run the command after the concurrent operation finishes — state is consistent because the original was restored.","Serialize access: run sync from one shell/job at a time, or add a lock around state-file management.","If it recurs, identify the second writer with lsof/fswatch on the state directory."],"exampleFix":"# before\n$ ecc codex sync & ecc codex sync &   # racing removals\n# Error: Legacy sync path changed before removal\n\n# after\n$ wait; ecc codex sync   # single serialized run","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { removeLegacyState(statePath); } catch (e) {\n  if (/changed before removal/.test(e.message)) {\n    // original was restored automatically; retry once after the concurrent writer exits\n    return removeLegacyState(statePath);\n  }\n  throw e;\n}","preventionTips":["One writer at a time: guard sync/remove operations with a lock so the swap race cannot happen.","Treat this error as a loud signal that two processes are managing the same state file."],"tags":["filesystem","race-condition","codex-sync"],"backgroundTag":"file-replaced-during-delete","analyzedSha":"06c5e118c4d3e6c3b7f9445f973a2194c82de193","analyzedAt":"2026-08-18T11:27:13.915Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}