denoland/deno · error · NodeTypeError

ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

Error message

The "fd" argument must be of type number

What it means

fs.readv(fd, buffers[, position], callback) requires fd to be a number (a raw file descriptor from fs.open/openSync). The polyfill checks typeof fd !== 'number' first and throws ERR_INVALID_ARG_TYPE — FileHandle objects, strings, and undefined all fail before getValidatedFd runs.

Source

Thrown at ext/node/polyfills/fs.ts:544

      );
    }
    offset += lengths[i];
  }
}

function readv(
  fd: number,
  buffers: readonly ArrayBufferView[],
  callback: ReadvCallback,
): void;
function readv(
  fd: number,
  buffers: readonly ArrayBufferView[],
  position: number | ReadvCallback,
  callback?: ReadvCallback,
): void {
  if (typeof fd !== "number") {
    throw new ERR_INVALID_ARG_TYPE("fd", "number", fd);
  }
  fd = getValidatedFd(fd);
  validateBufferArray(buffers);
  const cb = maybeCallback(callback || position) as ReadvCallback;
  let pos: number | null = null;
  if (typeof position === "number") {
    validateInteger(position, "position", 0);
    pos = position;
  }

  if (buffers.length === 0) {
    lazyProcess().default.nextTick(cb, null, 0, buffers);
    return;
  }
  const { buffer, lengths, views } = prepareReadvBuffers(buffers, false);

  PromisePrototypeThen(
    op_node_fs_read_deferred(fd, buffer, pos === null ? -1n : BigInt(pos)),

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Use the numeric descriptor: fs.readv(fh.fd, buffers, cb) or keep fs.openSync() results
  2. Convert external fd values: const n = Number(fd); if (!Number.isInteger(n)) throw ...
  3. Prefer fs.createReadStream / fh.read() when you already hold a FileHandle

Example fix

// before
const fh = await fsPromises.open('data.bin', 'r');
fs.readv(fh, [buf1, buf2], cb); // FileHandle is not a number -> throws

// after
fs.readv(fh.fd, [buf1, buf2], cb);
Defensive patterns

Strategy: type-guard

Validate before calling

const fdNum = typeof fd === 'object' && fd !== null && typeof fd.fd === 'number'
  ? fd.fd
  : fd;
if (typeof fdNum !== 'number' || !Number.isInteger(fdNum)) {
  throw new TypeError('readv requires a numeric fd (use fh.fd for FileHandle)');
}
fs.readv(fdNum, buffers, cb);

Type guard

const isNumericFd = (v) => typeof v === 'number' && Number.isInteger(v);

Prevention

When it happens

Trigger: const fh = await fsPromises.open(f); fs.readv(fh, buffers, cb) (FileHandle instead of fh.fd); fs.readv('3', bufs, cb) (string from CLI/config); forgetting the open() call and passing undefined.

Common situations: Mixing fsPromises (FileHandle) with callback-style fs APIs; fds arriving as strings from environment/IPC; refactors where openSync was replaced by fsPromises.open.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/0e5e51e3513cfe27. Report an issue: GitHub.