{"record":{"id":"389f009b22893dfd","repo":"Egonex-AI/Understand-Anything","slug":"output-file-missing-after-write-outputpath","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/extract-import-map.mjs","lineNumber":1954,"sourceCode":"      filesWithImports += 1;\n      totalEdges += resolved.length;\n    }\n  }\n\n  const output = {\n    scriptCompleted: true,\n    stats: {\n      filesScanned: files.length,\n      filesWithImports,\n      totalEdges,\n    },\n    importMap,\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    `extract-import-map: filesScanned=${files.length} ` +\n    `filesWithImports=${filesWithImports} totalEdges=${totalEdges}\\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.\n// ---------------------------------------------------------------------------","sourceCodeStart":1936,"sourceCodeEnd":1972,"githubUrl":"https://github.com/Egonex-AI/Understand-Anything/blob/32944829e7a63a9fa9c55d811d7f98a9530c6a6a/understand-anything-plugin/skills/understand/extract-import-map.mjs#L1936-L1972","documentation":"Thrown by extract-import-map.mjs immediately after writeFileSync(outputPath, ...) followed by existsSync(outputPath). The write call returned without throwing, yet the file is not present — a defensive check for filesystems where a successful write does not guarantee immediate visibility (network filesystems, container bind-mounts with caching, sandboxed FS layers).","triggerScenarios":"writeFileSync completes but existsSync immediately returns false. This happens on NFS / fuse / overlayfs with metadata caching, in some sandbox runtimes that intercept writes, or when outputPath is on a mount that silently drops the file (out-of-space on certain drivers, quota exceeded).","commonSituations":"Running the worker inside a sandboxed agent runtime that intercepts fs calls. outputPath on a network/share mount with deferred fsync visibility. Disk quota hit between write and stat. A path that crosses a mount boundary so the write and the stat hit different views. Concurrent cleanup that removed the file in the microsecond window.","solutions":["Confirm outputPath is on a local writable filesystem, not a network/share mount with metadata caching.","Check disk space and inode/quota on the target volume.","Retry the run; if it reproduces, capture fs.statSync right after write to see errno, and try fs.realpathSync(dirname(outputPath)) to confirm the directory still resolves.","Move outputPath to a tmpfs/local directory and have the caller read from there."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import { writeFileSync, existsSync, statSync, realpathSync } from 'node:fs';\nimport { dirname } from 'node:path';\nfunction safeWriteJson(path, value) {\n  writeFileSync(path, JSON.stringify(value, null, 2), 'utf-8');\n  if (!existsSync(path)) {\n    const dir = realpathSync(dirname(path));\n    throw new Error(`write invisible at ${path} (dir=${dir}); check mount/space`);\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 (e) { /* fall through to retry on transient fs */ }\n    await new Promise((r) => setTimeout(r, 100 * (i + 1)));\n  }\n  throw new Error(`output file missing after write: ${path}`);\n}","preventionTips":["Prefer a local filesystem for outputPath; avoid NFS/share mounts with metadata caching.","Free disk space and check inode quotas before large runs.","In sandboxed runtimes, write to a scratch/tmpfs path the runtime does not intercept."],"tags":["skill","import-map","filesystem","write-verification","sandbox"],"backgroundTag":null,"analyzedSha":"32944829e7a63a9fa9c55d811d7f98a9530c6a6a","analyzedAt":"2026-08-12T10:25:44.261Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}