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

  1. Ensure the path refers to a regular file; if it is a directory, correct the configured path or remove the directory
  2. Remove or replace any FIFO/socket/device node at the target path
  3. 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

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


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)