affaan-m/ECC · error · Error
Refusing to read a non-file at
Error message
Refusing to read a non-file at ${filePath}. What it means
readRegularFileSnapshot opens a file and, after fstat on the open descriptor, refuses to proceed if the opened object is not a regular file. This defends against reading directories, FIFOs, device files, or files swapped to non-regular types mid-read, which would produce garbage or block. The library deliberately fails closed rather than reading a non-regular inode.
Solutions
- Ensure the path refers to a regular file; if it is a directory, correct the configured path or remove the directory
- Remove or replace any FIFO/socket/device node at the target path
- Re-run the guided preview after fixing the filesystem state so the snapshot succeeds
Example fix
// before (statePath accidentally a directory)
fs.mkdirSync(statePath)
// after
fs.rmSync(statePath, { recursive: true })
runSetup({ /* installStatePath now a regular file path */ }) Defensive patterns
Strategy: validation
Validate before calling
const st = fs.lstatSync(filePath)
if (!st.isFile() || st.isSymbolicLink()) {
throw new Error(`${filePath} must be a regular file`)
} Type guard
const isRegularFile = (p) => { try { const s = fs.lstatSync(p); return s.isFile() && !s.isSymbolicLink() } catch { return false } } Try / catch
try {
snapshot(filePath)
} catch (err) {
if (err.message.includes('Refusing to read a non-file at')) {
console.error(`${filePath} is not a regular file; fix the path or remove the directory/FIFO`)
} else throw err
} Prevention
- lstat the target path before install operations and require a regular file
- Avoid placing install-state paths under directories that may be swapped with symlinks
- Audit target roots for stray FIFOs/sockets after failed runs
When it happens
Trigger: Passing a directory, named pipe, socket, or device path (or a symlink resolving to one) as a destination/state file path to snapshot/destination/classifyManagedOperation during guided install preview.
Common situations: Misconfigured target root pointing at a directory where a file was expected; a leftover FIFO or socket at the target path; a symlink redirected to /dev/null or a directory after a partially-failed install.
Related errors
- gate.variant_invalid
- Invalid ECC repo root: missing install script at
- Invalid ECC repo root: unreadable package.json at
- output artifact must be a regular file
- output bundle contains a symlink
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/e7d05188e75411a5.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/multi-harness-setup.js:88
&& left.size === right.size
&& left.mtimeMs === right.mtimeMs
&& left.ctimeMs === right.ctimeMs;
}
function readRegularFileSnapshot(filePath) {
const flags = fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW || 0);
let descriptor;
try {
descriptor = fs.openSync(filePath, flags);
} catch (error) {
if (error && (error.code === 'ENOENT' || error.code === 'ENOTDIR')) return null;
throw error;
}
try {
const before = fs.fstatSync(descriptor);
if (!before.isFile()) {
throw new Error(`Refusing to read a non-file at ${filePath}.`);
}
const content = fs.readFileSync(descriptor);
const after = fs.fstatSync(descriptor);
const finalPathStat = fs.lstatSync(filePath);
if (
finalPathStat.isSymbolicLink()
|| !finalPathStat.isFile()
|| !sameFileIdentity(before, after)
|| !sameFileIdentity(after, finalPathStat)
) {
throw new Error(`Refusing to read a file that changed during validation: ${filePath}.`);
}
return { content, stat: after };
} finally {
fs.closeSync(descriptor);
}
}
View on GitHub (pinned to 8321021c54)