{"record":{"id":"a29839056da388aa","repo":"affaan-m/ECC","slug":"legacy-sync-path-changed-while-opening-filepath","errorCode":null,"errorMessage":"Legacy sync path changed while opening: ${filePath}","messagePattern":"Legacy sync path changed while opening: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/codex-legacy-sync.js","lineNumber":48,"sourceCode":"      } catch (lstatError) {\n        if (lstatError.code === 'ENOENT') return null;\n        throw lstatError;\n      }\n      throw error;\n    }\n    if (error.code === 'ELOOP') {\n      throw new Error(`Refusing to manage non-regular legacy sync path: ${filePath}`);\n    }\n    throw error;\n  }\n  const descriptorStat = fs.fstatSync(descriptor, { bigint: true });\n  let finalPathStat;\n  try {\n    finalPathStat = fs.lstatSync(filePath, { bigint: true });\n  } catch (error) {\n    fs.closeSync(descriptor);\n    if (error.code === 'ENOENT') {\n      throw new Error(`Legacy sync path changed while opening: ${filePath}`);\n    }\n    throw error;\n  }\n  if (\n    !descriptorStat.isFile()\n    || !finalPathStat.isFile()\n    || finalPathStat.isSymbolicLink()\n    || descriptorStat.dev !== finalPathStat.dev\n    || descriptorStat.ino !== finalPathStat.ino\n    || descriptorStat.nlink !== 1n\n    || finalPathStat.nlink !== 1n\n  ) {\n    fs.closeSync(descriptor);\n    throw new Error(`Refusing to manage non-regular legacy sync path: ${filePath}`);\n  }\n  return { descriptor, stat: fs.fstatSync(descriptor) };\n}\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/codex-legacy-sync.js#L30-L66","documentation":"openRegularFileNoFollow opens a path with O_NOFOLLOW, then re-lstats the path to verify the file did not change during the open. If the second lstatSync fails with ENOENT, the file at the path was removed or renamed between the open and the verification check, so the library aborts rather than operating on a vanished or swapped target. This is part of the TOCTOU hardening that guards legacy codex sync files against symlink and race attacks.","triggerScenarios":"Another process unlinks or renames filePath in the window between fs.openSync and the fs.lstatSync(filePath, { bigint: true }) verification inside openRegularFileNoFollow; reached via opened(), quarantined(), rollbackLegacyCodexSync(), or uninstallLegacyCodexSync().","commonSituations":"A concurrent install/uninstall or npm operation removes the legacy codex sync file while this script runs; antivirus or cleanup tools quarantine the file mid-operation; two copies of the script racing on the same path.","solutions":["Re-run the uninstall/rollback command once no other process is touching the repository","Check that the target file exists (fs.lstatSync) before invoking rollback/uninstall and skip if already gone","Ensure only one instance of the script runs at a time (use a lockfile or flock)","Exclude the sync path from antivirus/cleanup watchers that may remove files mid-operation"],"exampleFix":"// before\nawait uninstallLegacyCodexSync(targetPath);\n// after\nimport fs from 'node:fs';\nlet exists = true;\ntry { fs.lstatSync(targetPath); } catch (e) { if (e.code === 'ENOENT') exists = false; else throw e; }\nif (exists) await uninstallLegacyCodexSync(targetPath);","handlingStrategy":"try-catch","validationCode":"import fs from 'node:fs';\nlet exists = false;\ntry { const s = fs.lstatSync(p); exists = s.isFile(); } catch (e) { if (e.code !== 'ENOENT') throw e; }\nif (!exists) return; // nothing to uninstall/roll back","typeGuard":null,"tryCatchPattern":"try {\n  await uninstallLegacyCodexSync(p);\n} catch (err) {\n  if (err.message.includes('Legacy sync path changed while opening')) {\n    // file vanished mid-operation; treat as already removed\n  } else throw err;\n}","preventionTips":["Check file existence with lstat before calling rollback/uninstall","Run only one instance of the script at a time (lockfile/flock)","Exclude the sync path from antivirus or cleanup daemons","Retry the operation once on this error; the path state is now stable"],"tags":["filesystem","race-condition","symlink-safety","toctou"],"backgroundTag":"file-not-found","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}