Egonex-AI/Understand-Anything · error · Error
output file missing after write: ${outputPath}
Error message
output file missing after write: ${outputPath} What it means
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).
Source
Thrown at understand-anything-plugin/skills/understand/extract-import-map.mjs:1954
filesWithImports += 1;
totalEdges += resolved.length;
}
}
const output = {
scriptCompleted: true,
stats: {
filesScanned: files.length,
filesWithImports,
totalEdges,
},
importMap,
};
writeFileSync(outputPath, JSON.stringify(output, null, 2), 'utf-8');
if (!existsSync(outputPath)) {
throw new Error(`output file missing after write: ${outputPath}`);
}
process.stderr.write(
`extract-import-map: filesScanned=${files.length} ` +
`filesWithImports=${filesWithImports} totalEdges=${totalEdges}\n`,
);
}
// ---------------------------------------------------------------------------
// Run only when executed directly as a CLI; importing the module (e.g. from
// tests) must not trigger main().
//
// Canonicalize both sides through realpathSync. Node ESM resolves
// import.meta.url through symlinks but pathToFileURL(process.argv[1]) preserves
// them, so a raw equality check silently no-ops when the script is invoked via
// a symlinked plugin install path (the default in Claude Code / Copilot CLI
// caches). See GitHub issue #162.
// ---------------------------------------------------------------------------View on GitHub (pinned to 32944829e7)
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.
Defensive patterns
Strategy: retry
Validate before calling
import { writeFileSync, existsSync, statSync, realpathSync } from 'node:fs';
import { dirname } from 'node:path';
function safeWriteJson(path, value) {
writeFileSync(path, JSON.stringify(value, null, 2), 'utf-8');
if (!existsSync(path)) {
const dir = realpathSync(dirname(path));
throw new Error(`write invisible at ${path} (dir=${dir}); check mount/space`);
}
} Try / catch
async function writeWithRetry(path, value, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
writeFileSync(path, JSON.stringify(value, null, 2), 'utf-8');
if (existsSync(path)) return;
} catch (e) { /* fall through to retry on transient fs */ }
await new Promise((r) => setTimeout(r, 100 * (i + 1)));
}
throw new Error(`output file missing after write: ${path}`);
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- output file missing after write: ${outputPath}
- output file missing after write: ${outputPath}
- Invalid input: must contain projectRoot and files array
- Unable to remove temporary benchmark artifacts
- Repository path does not exist: ${repoValue}
AI-assisted analysis of Egonex-AI/Understand-Anything@32944829e7 (2026-08-12).
Data as JSON: /api/errors/389f009b22893dfd.
Report an issue: GitHub.