{"record":{"id":"7064ef2cba439f6b","repo":"denoland/deno","slug":"err-invalid-fd-7064ef","errorCode":"ERR_INVALID_FD","errorMessage":"\"fd\" must be a positive integer: ${fd}","messagePattern":"\"fd\" must be a positive integer: (.+?)","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/tty_esm.ts","lineNumber":31,"sourceCode":"} = primordials;\nconst {\n  ERR_INVALID_FD,\n  ERR_TTY_INIT_FAILED,\n} = core.loadExtScript(\"ext:deno_node/internal/errors.ts\");\n\nconst { isatty } = core.loadExtScript(\"ext:deno_node/tty.js\");\n\n// ReadStream needs to be callable without `new` to match Node.js behavior.\n// We use a wrapper function that delegates to the actual class.\n// deno-lint-ignore no-explicit-any\nfunction ReadStream(this: any, fd: number, options?: unknown) {\n  if (!ObjectPrototypeIsPrototypeOf(ReadStream.prototype, this)) {\n    // deno-lint-ignore no-explicit-any\n    return new (ReadStream as any)(fd, options);\n  }\n\n  if (fd >> 0 !== fd || fd < 0) {\n    throw new ERR_INVALID_FD(fd);\n  }\n\n  // Non-stdio fds require --allow-all\n  op_tty_check_fd_permission(fd);\n\n  // deno-lint-ignore no-explicit-any\n  const ctx: any = {};\n  const tty = new TTY(fd, ctx);\n  if (ctx.code !== undefined) {\n    throw new ERR_TTY_INIT_FAILED(ctx);\n  }\n  FunctionPrototypeCall(Socket, this, {\n    readableHighWaterMark: 0,\n    handle: tty,\n    manualStart: true,\n    // deno-lint-ignore no-explicit-any\n    ...(options as any),\n  });","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/tty_esm.ts#L13-L49","documentation":"The legacy tty.ReadStream constructor validates fd before anything else: fd must satisfy `fd >> 0 === fd && fd >= 0`, i.e. a non-negative int32 integer. Negative numbers, fractions, NaN, strings, BigInts, or values above 2147483647 throw ERR_INVALID_FD; fd 0 (stdin) is accepted despite the 'positive integer' message wording. After this check, non-stdio fds additionally require --allow-all permission in Deno.","triggerScenarios":"`new tty.ReadStream(process.argv[2])` with an unconverted string; a fractional fd like 1.5; a negative sentinel like -1; `parseInt(x)` returning NaN; fds above 2^31-1 obtained from another API.","commonSituations":"Reading fd numbers from environment variables or CLI args without Number(); fd variables that are undefined after a failed lookup; code ported from runtimes with different fd validation rules.","solutions":["Convert with Number() and validate: `Number.isInteger(fd) && fd >= 0 && fd <= 0x7fffffff`","Use process.stdin/stdout/stderr or the literal fds 0, 1, 2 instead of raw numbers","Grant --allow-all when wrapping fds beyond stdio in Deno (op_tty_check_fd_permission)","Prefer tty.isatty(fd) checks plus high-level stream APIs over constructing ReadStream directly"],"exampleFix":"// before\nconst fd = process.env.FD; // string from env\nnew tty.ReadStream(fd); // ERR_INVALID_FD\n\n// after\nconst fd = Number(process.env.FD);\nif (!Number.isInteger(fd) || fd < 0 || fd > 0x7fffffff) {\n  throw new RangeError(`bad fd: ${process.env.FD}`);\n}\nnew tty.ReadStream(fd);","handlingStrategy":"type-guard","validationCode":"const fd = Number(rawFd);\nif (!Number.isInteger(fd) || fd < 0 || fd > 0x7fffffff) {\n  throw new Error(`fd must be a non-negative int32, got ${String(rawFd)}`);\n}\nconst rs = new tty.ReadStream(fd);","typeGuard":"const isValidFd = (fd: unknown): fd is number =>\n  typeof fd === \"number\" &&\n  Number.isInteger(fd) &&\n  fd >= 0 &&\n  fd <= 0x7fffffff;","tryCatchPattern":"try {\n  stream = new tty.ReadStream(fd);\n} catch (e: any) {\n  if (e?.code === \"ERR_INVALID_FD\") {\n    throw new Error(`invalid fd from configuration: ${String(fd)}`);\n  }\n  throw e;\n}","preventionTips":["Convert fd strings from argv/env with Number() and validate before use","Prefer process.stdin/stdout objects over numeric fds","Remember non-stdio fds need --allow-all under Deno"],"tags":["tty","file-descriptor","node-compat","validation"],"backgroundTag":"invalid-file-descriptor","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}