{"record":{"id":"1315c645afbcfbe2","repo":"Egonex-AI/Understand-Anything","slug":"output-file-missing-after-write-outputpath-1315c6","errorCode":null,"errorMessage":"output file missing after write: ${outputPath}","messagePattern":"output file missing after write: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"understand-anything-plugin/skills/understand/scan-project.mjs","lineNumber":868,"sourceCode":"\n  const output = {\n    scriptCompleted: true,\n    contentDigest,\n    files: fileEntries,\n    totalFiles: fileEntries.length,\n    filteredByIgnore,\n    estimatedComplexity,\n    stats: {\n      filesScanned: fileEntries.length,\n      byCategory,\n      byLanguage,\n    },\n  };\n\n  writeFileSync(outputPath, JSON.stringify(output, null, 2), 'utf-8');\n\n  if (!existsSync(outputPath)) {\n    throw new Error(`output file missing after write: ${outputPath}`);\n  }\n\n  process.stderr.write(\n    `scan-project: filesScanned=${fileEntries.length} ` +\n    `filteredByIgnore=${filteredByIgnore} ` +\n    `complexity=${estimatedComplexity}\\n`,\n  );\n}\n\n// ---------------------------------------------------------------------------\n// Run only when executed directly as a CLI; importing the module (e.g. from\n// tests) must not trigger main().\n//\n// Canonicalize both sides through realpathSync. Node ESM resolves\n// import.meta.url through symlinks but pathToFileURL(process.argv[1]) preserves\n// them, so a raw equality check silently no-ops when the script is invoked via\n// a symlinked plugin install path (the default in Claude Code / Copilot CLI\n// caches). See GitHub issue #162.","sourceCodeStart":850,"sourceCodeEnd":886,"githubUrl":"https://github.com/Egonex-AI/Understand-Anything/blob/32944829e7a63a9fa9c55d811d7f98a9530c6a6a/understand-anything-plugin/skills/understand/scan-project.mjs#L850-L886","documentation":"Thrown by scan-project.mjs main() immediately after writeFileSync(outputPath, ...) followed by existsSync(outputPath). The third instance of the defensive write-then-verify pattern (also in extract-import-map and extract-structure). Guards against filesystems where a returned-without-error write is not yet observable by stat.","triggerScenarios":"writeFileSync completes but existsSync(outputPath) returns false. Network/overlay/fuse mounts with metadata caching, sandboxed agent runtimes intercepting fs, or quota/inode exhaustion on certain drivers.","commonSituations":"Agent sandbox runtime intercepting writes. outputPath on NFS/share with deferred visibility. Disk-full or out-of-inodes between write and stat. Path crossing a mount boundary. Concurrent process removing the file in the window between write and stat.","solutions":["Put outputPath on a local writable filesystem.","Check free space and inode quota on the target volume.","Retry; on reproduction, capture fs.statSync errno and realpathSync(dirname(outputPath)).","Use a tmpfs/scratch directory for outputPath."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import { writeFileSync, existsSync } from 'node:fs';\nfunction safeWriteJson(path, value) {\n  writeFileSync(path, JSON.stringify(value, null, 2), 'utf-8');\n  if (!existsSync(path)) {\n    throw new Error(`write invisible at ${path}; check mount/space/quota`);\n  }\n}","typeGuard":null,"tryCatchPattern":"async function writeWithRetry(path, value, attempts = 3) {\n  for (let i = 0; i < attempts; i++) {\n    try {\n      writeFileSync(path, JSON.stringify(value, null, 2), 'utf-8');\n      if (existsSync(path)) return;\n    } catch {}\n    await new Promise((r) => setTimeout(r, 100 * (i + 1)));\n  }\n  throw new Error(`output file missing after write: ${path}`);\n}","preventionTips":["Keep outputPath on a local writable filesystem.","Verify free space and inode quota before the run.","Use a tmpfs/scratch directory inside sandboxed runtimes."],"tags":["skill","scan-project","filesystem","write-verification","sandbox"],"backgroundTag":null,"analyzedSha":"32944829e7a63a9fa9c55d811d7f98a9530c6a6a","analyzedAt":"2026-08-12T10:25:44.261Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}