parcel-bundler/parcel · error · FSError

EMFILE

EMFILE

Error message

EMFILE: ${path} no available file descriptor

What it means

EMFILE raised by `ExtendedMemoryFS._nextFD` when the in-memory FS has `FD_MAX` open file descriptors and none are free. This is a descriptor leak: opens without matching closes exhaust the table.

Source

Thrown at packages/dev/repl/src/parcel/ExtendedMemoryFS.js:267

    throw new FSError('ENOENT', path.dirname(oldPath), "wasn't found");
  }

  _nextFD(path: FilePath): number {
    let tested = 0;
    let fd;
    while (tested < FD_MAX) {
      let candidate = this.nextFD++;
      if (candidate >= FD_MAX) {
        this.nextFD = 1;
        candidate = this.nextFD++;
      }
      if (!this.openFDs.has(candidate)) {
        fd = candidate;
        break;
      }
    }
    if (!fd) {
      throw new FSError('EMFILE', path, 'no available file descriptor');
    }
    return fd;
  }

  openSync(filePath: FilePath, flags: number, mode: number): number {
    flags = parseOpenFlags(flags);
    if (flags & CONSTANTS.O_NOFOLLOW && this.symlinks.has(filePath)) {
      throw new FSError('ELOOP', filePath, 'is a symlink');
    }

    filePath = this._normalizePath(filePath);

    let file = this.files.get(filePath);
    if (flags & CONSTANTS.O_CREAT) {
      if (file) {
        if (flags & CONSTANTS.O_EXCL) {
          throw new FSError('EEXIST', filePath, 'already exists');
        }

View on GitHub (pinned to 59484858a1)

Solutions

  1. Ensure every successful `openSync` is paired with `closeSync` in a finally block.
  2. Limit concurrent opens with a small pool/queue.
  3. If FD_MAX is genuinely too low for your workload, raise it in the FS config — but a leak is the more likely cause.

Example fix

// before
const fd = fs.openSync(p, O_RDONLY);
use(fs.readSync(fd, ...));
// after
const fd = fs.openSync(p, O_RDONLY);
try { use(fs.readSync(fd, ...)); }
finally { fs.closeSync(fd); }
Defensive patterns

Strategy: try-catch

Validate before calling

function assertFDFree(fs) {
  // expose openFDs size; fail fast before openSync if near FD_MAX
  if (fs.openFDs.size >= FD_MAX) throw new Error('FD table full — close handles');
}

Try / catch

let fd;
try { fd = fs.openSync(p, flags); /* ... */ }
finally { if (fd != null) fs.closeSync(fd); }

Prevention

When it happens

Trigger: Repeated `openSync` without `closeSync`, exceeding FD_MAX; a transformer/packager that opens many files concurrently and forgets to close them.

Common situations: Long-running REPL sessions that accumulate handles; bulk operations opening many assets; missing `fs.closeSync(fd)` after reads/writes.

Related errors


AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13). Data as JSON: /api/errors/1cb9d3c978bcf96e. Report an issue: GitHub.