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

  1. Inspect the path (ls -la, stat) and remove any special file occupying it, then re-run rollback
  2. Re-run the rollback command when no other process is writing to the path
  3. Move the operation to a local filesystem instead of a network/FUSE mount
  4. 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

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


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)