{"record":{"id":"5e32e46b37708e3b","repo":"affaan-m/ECC","slug":"label-must-remain-a-regular-non-symlink-file-w","errorCode":null,"errorMessage":"${label} must remain a regular, non-symlink file while it is opened.","messagePattern":"(.+?) must remain a regular, non-symlink file while it is opened\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/memory-vault.js","lineNumber":164,"sourceCode":"    assertWithinTrustedRoot(filePath, options.trustedRoot, `read ${label}`);\n  }\n\n  const flags = fs.constants.O_RDONLY\n    | (fs.constants.O_NOFOLLOW || 0)\n    | (fs.constants.O_NONBLOCK || 0);\n  const descriptor = fs.openSync(filePath, flags);\n  try {\n    const opened = fs.fstatSync(descriptor, { bigint: true });\n    if (!opened.isFile()) {\n      throw new Error(`${label} must be a regular, non-symlink file.`);\n    }\n    const after = fs.lstatSync(filePath, { bigint: true });\n    if (\n      after.isSymbolicLink()\n      || !after.isFile()\n      || !sameFileIdentity(after, opened)\n    ) {\n      throw new Error(`${label} must remain a regular, non-symlink file while it is opened.`);\n    }\n    if (options.trustedRoot) {\n      assertWithinTrustedRoot(filePath, options.trustedRoot, `read ${label}`);\n    }\n    if (opened.size > BigInt(maxBytes)) {\n      throw new Error(`${label} is too large (${opened.size} bytes).`);\n    }\n\n    const chunks = [];\n    let total = 0;\n    while (total <= maxBytes) {\n      const buffer = Buffer.alloc(Math.min(64 * 1024, maxBytes + 1 - total));\n      const bytesRead = fs.readSync(descriptor, buffer, 0, buffer.length, null);\n      if (bytesRead === 0) break;\n      chunks.push(buffer.subarray(0, bytesRead));\n      total += bytesRead;\n    }\n    if (total > maxBytes) {","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/memory-vault.js#L146-L182","documentation":"readRegularTextFile re-checks the path with lstat after opening and throws when the file was swapped to a symlink, ceased to be a regular file, or its identity (dev) changed mid-read — a TOCTOU/race guard. The faulting input is the file at `label` being concurrently replaced.","triggerScenarios":"Thrown at scripts/lib/memory-vault.js:164 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Retry the read once no other process is rewriting the file.","Exclude the memory vault from concurrent writers/sync tools during reads.","Investigate what is swapping the file if this recurs — likely a sync or editor tool racing the vault."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}