{"record":{"id":"1df467602b3decf6","repo":"affaan-m/ECC","slug":"label-must-be-a-regular-non-symlink-file","errorCode":null,"errorMessage":"${label} must be a regular, non-symlink file.","messagePattern":"(.+?) must be a regular, non-symlink file\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/memory-vault.js","lineNumber":156,"sourceCode":"  }\n  return left.dev === right.dev;\n}\n\nfunction readRegularTextFile(filePath, options = {}) {\n  const label = options.label || 'file';\n  const maxBytes = options.maxBytes || MAX_DOCUMENT_BYTES;\n  if (options.trustedRoot) {\n    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;","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/memory-vault.js#L138-L174","documentation":"readRegularTextFile opened the target with O_RDONLY | O_NOFOLLOW | O_NONBLOCK, but fstat on the resulting descriptor reports a non-regular file. O_NOFOLLOW only rejects a symlink as the final path component; it still succeeds for FIFOs, devices, sockets, and other non-regular inodes. The vault rejects these because memory documents must be plain files that can be size-checked, streamed, and fsynced safely.","triggerScenarios":"A memory document path (or the project .gitignore) resolves to a FIFO, character/block device, socket, or other special file. Triggered by readRegularTextFile via readMemoryFiles scanning the vault, ensureProjectScopeIgnored reading .gitignore, or any direct call passing a special file path.","commonSituations":"A prank or misconfigured script creating a FIFO (mkfifo) named like a memory file; a broken backup that restored a device node; /dev/null or /dev/zero accidentally referenced; an external tool writing a Unix socket inside the vault directory; filesystem corruption exposing a special inode.","solutions":["Identify the file at the reported path and remove it: rm <path>.","If legitimate memory content existed there, restore it from a backup as a real file (printf '%s' \"$content\" > <path> or re-run saveMemory).","Audit the vault directory for non-regular files: find <root> -type f ! -type r ... or scan with find <root> ! -type d and check each entry.","Run doctorMemoryVault to surface and quarantine the invalid file."],"exampleFix":"// before: .ecc/memory/project/notes/mem_x.md is a FIFO (mkfifo)\n// shell fix:\n//   rm .ecc/memory/project/notes/mem_x.md\n//   node -e \"require('./scripts/lib/memory-vault').saveMemory({title:'x',body:'...'})\"\n// after: mem_x.md is a regular file","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nfunction assertRegularFile(p) {\n  if (!fs.existsSync(p)) return false;\n  const st = fs.lstatSync(p);\n  return st.isFile() && !st.isSymbolicLink();\n}\n// before reading:\nif (!assertRegularFile(filePath)) throw new Error(`${filePath} must be a regular, non-symlink file.`);","typeGuard":"function isRegularNonSymlinkFile(p) {\n  try { const st = fs.lstatSync(p); return st.isFile() && !st.isSymbolicLink(); }\n  catch { return false; }\n}","tryCatchPattern":"try { readRegularTextFile(filePath, { trustedRoot: root }); }\ncatch (error) {\n  if (/regular, non-symlink file/.test(error.message)) {\n    console.error('Special or non-regular file in vault:', error.message);\n    return;\n  }\n  throw error;\n}","preventionTips":["Only ever write vault files through saveMemory / writeCreateOnlyTextFile — never mkfifo, mknod, or socket calls inside the vault.","Audit the vault for non-regular files: find <root> ! -type d ! -type f.","Run doctorMemoryVault regularly; invalid files show up in the invalidFiles list.","Treat any non-.md file in the vault as suspicious."],"tags":["security","filesystem","memory-vault","validation"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}