{"record":{"id":"e7ad5c6acf790306","repo":"denoland/deno","slug":"err-invalid-fd-type-e7ad5c","errorCode":"ERR_INVALID_FD_TYPE","errorMessage":"Unsupported fd type: ${type}","messagePattern":"Unsupported fd type: (.+?)","errorType":"error_code","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/net.ts","lineNumber":436,"sourceCode":"\nfunction _isPipeName(s: unknown): s is string {\n  return typeof s === \"string\" && _toNumber(s) === false;\n}\n\nfunction _createHandle(fd: number, isServer: boolean): Handle {\n  validateInt32(fd, \"fd\", 0);\n\n  const type = guessHandleType(fd);\n\n  if (type === \"PIPE\") {\n    return new Pipe(isServer ? PipeConstants.SERVER : PipeConstants.SOCKET);\n  }\n\n  if (type === \"TCP\") {\n    return new TCP(isServer ? TCPConstants.SERVER : TCPConstants.SOCKET);\n  }\n\n  throw new ERR_INVALID_FD_TYPE(type);\n}\n\n// Returns an array [options, cb], where options is an object,\n// cb is either a function or null.\n// Used to normalize arguments of `Socket.prototype.connect()` and\n// `Server.prototype.listen()`. Possible combinations of parameters:\n// - (options[...][, cb])\n// - (path[...][, cb])\n// - ([port][, host][...][, cb])\n// For `Socket.prototype.connect()`, the [...] part is ignored\n// For `Server.prototype.listen()`, the [...] part is [, backlog]\n// but will not be handled here (handled in listen())\nfunction _normalizeArgs(args: unknown[]): NormalizedArgs {\n  let arr: NormalizedArgs;\n\n  if (args.length === 0) {\n    arr = [{}, null];\n    arr[normalizedArgsSymbol] = true;","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/net.ts#L418-L454","documentation":"When a net Socket or Server is created from a raw file descriptor (new net.Socket({ fd }) or server.listen({ fd })), _createHandle asks the OS-level guessHandleType and only supports 'PIPE' and 'TCP'. Any other fd type — TTY (terminal), FILE (regular file, /dev/null), UDP — throws ERR_INVALID_FD_TYPE with the guessed type name.","triggerScenarios":"server.listen({ fd: 0 }) while stdin is a terminal (type TTY); passing the fd of a regular file or /dev/null; wrapping a UDP socket fd from dgram into net; systemd-style fd handoff where the fd is not a socket/pipe.","commonSituations":"Systemd socket-activation code tested interactively (fd 0 becomes a TTY instead of the activated socket); scripts that try to serve over stdout redirected to a file; cluster fd-passing patterns on unsupported handle kinds.","solutions":["Only pass fds that are actual sockets (TCP) or pipes — e.g. from socketpair, pipe(2), or a real activated socket","Guard interactive/dev runs: skip the fd path unless the fd is known to be a socket (in dev, listen on a port instead)","For dgram fds use node:dgram APIs, not net"],"exampleFix":"// before\nserver.listen({ fd: Number(process.env.LISTEN_FDS) ? 3 : 0 }); // fd 0 is a TTY in dev\n\n// after\nconst fd = Number(process.env.LISTEN_FDS) > 0 ? 3 : undefined;\nif (fd !== undefined) server.listen({ fd });\nelse server.listen(3000);","handlingStrategy":"try-catch","validationCode":"const isPosixSocketLike = (fd: number) => {\n  try {\n    const st = Deno.fstatSync(fd as any); // Deno-only probe\n    return st.mode != null && (st.mode & 0o140000) === 0o140000; // S_IFSOCK\n  } catch { return false; }\n};","typeGuard":null,"tryCatchPattern":"try {\n  server.listen({ fd });\n} catch (e: any) {\n  if (e?.code === 'ERR_INVALID_FD_TYPE') server.listen(3000); // dev fallback: plain port\n  else throw e;\n}","preventionTips":["Only hand socket/pipe fds to net (socketpair, pipe(2), systemd-activated sockets)","In dev, branch on the presence of the activation env (LISTEN_FDS) and listen on a port otherwise","Remember stdin/stdout type depends on how the process was launched (TTY vs pipe vs file)"],"tags":["network","sockets","file-descriptors","node-compat"],"backgroundTag":"invalid-fd-type","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}