{"record":{"id":"ac132935a0254075","repo":"denoland/deno","slug":"err-invalid-handle-type","errorCode":"ERR_INVALID_HANDLE_TYPE","errorMessage":"This handle type cannot be sent","messagePattern":"This handle type cannot be sent","errorType":"exception","errorClass":"NodeTypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/child_process.ts","lineNumber":2279,"sourceCode":"  if (!socketLists) {\n    socketLists = new SafeWeakMap();\n    socketListsByChild.set(child, socketLists);\n  }\n  let socketList = socketLists.get(server);\n  if (!socketList) {\n    socketList = new SocketListSend(child, server);\n    socketLists.set(server, socketList);\n  }\n  return socketList;\n}\n\nfunction rawFdFromTcpHandle(tcpHandle) {\n  if (typeof tcpHandle.fdForIpc !== \"function\") {\n    notImplemented(\"ChildProcess.send with handle on this platform\");\n  }\n  const rawFd = tcpHandle.fdForIpc();\n  if (rawFd < 0) {\n    throw new ERR_INVALID_HANDLE_TYPE();\n  }\n  return rawFd;\n}\n\nfunction getIpcHandleInfo(handle, options, target) {\n  const { Socket } = lazyNet();\n  const { Server: NetServer } = lazyNet();\n  const { Socket: DgramSocket } = lazyDgram();\n  if (ObjectPrototypeIsPrototypeOf(Socket.prototype, handle)) {\n    const inner = handle._handle;\n    // Match Node's handleConversion[\"net.Socket\"].send, which returns the\n    // socket's native handle. A socket without an underlying handle (e.g.\n    // already destroyed) yields null; Node then strips the handle and sends\n    // the message alone instead of throwing.\n    if (!inner) {\n      return null;\n    }\n    const isTcp = ObjectPrototypeIsPrototypeOf(TCP.prototype, inner);","sourceCodeStart":2261,"sourceCodeEnd":2297,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/child_process.ts#L2261-L2297","documentation":"When a net.Socket is sent over IPC (child.send(message, socket)), the polyfill extracts a raw file descriptor the receiving process can re-open. rawFdFromTcpHandle throws ERR_INVALID_HANDLE_TYPE when the TCP handle's fdForIpc() returns a negative value — the socket exists but has no fd shareable across processes. Node applies the same rule: sockets whose descriptor cannot be duplicated are rejected.","triggerScenarios":"child.send(\"go\", socket) where socket is a net.Socket whose fdForIpc() returns < 0 (closed, not yet connected, or otherwise unshareable); forwarding handles between cluster workers in the wrong lifecycle state.","commonSituations":"Sending TLS-wrapped or already-destroyed sockets; custom IPC proxies that forward handles before the connection settles; platforms where fd sharing is limited (the adjacent notImplemented path fires where fdForIpc is unavailable).","solutions":["Ensure the socket is fully connected and not destroyed before send()","Do not send TLS/HTTPS sockets; send the underlying plain net.Socket or connection metadata","On failure, fall back to sending { host, port } and let the child reconnect itself","Wrap send() in try-catch keyed on err.code === \"ERR_INVALID_HANDLE_TYPE\" and degrade gracefully"],"exampleFix":"// before\nconst sock = tls.connect(443, host);\nsock.on(\"secureConnect\", () => child.send(\"conn\", sock)); // TLS socket not shareable\n\n// after\nconst sock = net.connect(80, host);\nsock.on(\"connect\", () => {\n  try {\n    child.send(\"conn\", sock);\n  } catch (err) {\n    if (err.code === \"ERR_INVALID_HANDLE_TYPE\") {\n      child.send(\"conn-info\", { host, port: 80 });\n    } else throw err;\n  }\n});","handlingStrategy":"try-catch","validationCode":"if (!(socket instanceof net.Socket) || socket.destroyed || socket.pending) {\n  throw new Error(\"socket is not in a shareable state for IPC\");\n}","typeGuard":"const isShareableTcpSocket = (s) => s instanceof net.Socket && !s.destroyed && !s.pending;","tryCatchPattern":"try {\n  child.send(msg, socket);\n} catch (err) {\n  if (err.code === \"ERR_INVALID_HANDLE_TYPE\") {\n    child.send(msg, { host, port }); // fall back to reconnect-style handoff\n  } else {\n    throw err;\n  }\n}","preventionTips":["Only send freshly connected, non-destroyed net.Socket handles","Never send TLS/HTTPS sockets; send the underlying socket before upgrade, or metadata","Treat ERR_INVALID_HANDLE_TYPE as a signal to fall back to a metadata handoff"],"tags":["child-process","ipc","sockets","cluster"],"backgroundTag":"ipc-handle-passing","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}