affaan-m/ECC · error · Error
Refusing to create non-regular legacy sync path
Error message
Refusing to create non-regular legacy sync path: ${filePath} What it means
createRegularFileNoFollow creates a new file with O_CREAT|O_EXCL|O_NOFOLLOW and then fstats the descriptor to confirm it is a regular file. If the freshly created node is not a regular file, the creation raced with something that substituted a non-regular object at the path (or an unusual filesystem returned an unexpected node), so the library refuses to write content into it and throws.
Solutions
- Inspect the path (ls -la, stat) and remove any special file occupying it, then re-run rollback
- Re-run the rollback command when no other process is writing to the path
- Move the operation to a local filesystem instead of a network/FUSE mount
- On a shared host, tighten permissions on the parent directory so other users cannot swap the path
Example fix
# before: check what occupies the path ls -la <path> # shows p (FIFO), s (socket), etc. # after: remove the special file and retry rollback rm <path> npm run <rollback-command>
Defensive patterns
Strategy: try-catch
Validate before calling
import fs from 'node:fs';
try { fs.lstatSync(p); } catch (e) { if (e.code !== 'ENOENT') { /* path occupied by something odd */ } }
// ensure parent dir is on a local filesystem and writable by the current user only Try / catch
try {
await rollbackLegacyCodexSync(p);
} catch (err) {
if (err.message.includes('Refusing to create non-regular legacy sync path')) {
// inspect the path for special files, remove, and retry
} else throw err;
} Prevention
- Run rollback on a local POSIX filesystem, not NFS/FUSE mounts
- Ensure no other process writes to the path during rollback
- Restrict parent directory permissions (0o755 or tighter) on multi-user hosts
- Remove any FIFO/socket/device occupying the target path before running
When it happens
Trigger: Called from rollbackLegacyCodexSync when recreating a legacy sync file: after openSync succeeds, fs.fstatSync reports the descriptor is not a regular file — e.g. a concurrent process replaced the path with a FIFO/socket/device between the create and the stat, or a non-POSIX filesystem (some network mounts) reports an unexpected type.
Common situations: Another tool re-creates the sync path as a FIFO or special file while rollback runs; exotic network filesystems (NFS with odd semantics, FUSE mounts) misreporting file types; adversarial race on a shared multi-user machine.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Legacy sync path changed while opening
- Memory destination changed while it was being created.
- Refusing to read a file that changed during validation
- artifact byte count exceeded during reading
- artifact changed before reading
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/516d220a514c579c.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/codex-legacy-sync.js:95
}
}
function replaceOpenedRegularFile(opened, content, mode = null) {
const buffer = Buffer.isBuffer(content) ? content : Buffer.from(content);
fs.ftruncateSync(opened.descriptor, 0);
fs.writeSync(opened.descriptor, buffer, 0, buffer.length, 0);
if (mode) fs.fchmodSync(opened.descriptor, mode);
fs.fsyncSync(opened.descriptor);
}
function createRegularFileNoFollow(filePath, content, mode = 0o600) {
const noFollow = fs.constants.O_NOFOLLOW || 0;
const flags = fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | noFollow;
const descriptor = fs.openSync(filePath, flags, mode);
try {
const stat = fs.fstatSync(descriptor);
if (!stat.isFile()) {
throw new Error(`Refusing to create non-regular legacy sync path: ${filePath}`);
}
fs.writeFileSync(descriptor, content);
fs.fchmodSync(descriptor, mode);
fs.fsyncSync(descriptor);
} finally {
fs.closeSync(descriptor);
}
}
function removeOpenedRegularFile(filePath, opened) {
const quarantineDir = fs.mkdtempSync(path.join(path.dirname(filePath), '.ecc-remove-'));
const quarantinePath = path.join(quarantineDir, path.basename(filePath));
fs.renameSync(filePath, quarantinePath);
const quarantined = openRegularFileNoFollow(quarantinePath);
const openedStat = fs.fstatSync(opened.descriptor, { bigint: true });
const quarantinedStat = fs.fstatSync(quarantined.descriptor, { bigint: true });
fs.closeSync(quarantined.descriptor);
fs.closeSync(opened.descriptor);View on GitHub (pinned to 8321021c54)