{"record":{"id":"dcbfe924a1e4b07a","repo":"denoland/deno","slug":"invalid-handle","errorCode":null,"errorMessage":"Invalid handle","messagePattern":"Invalid handle","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"runtime/subprocess_windows/src/process_stdio.rs","lineNumber":174,"sourceCode":"  unsafe {\n    copy_handle(\n      child_stdio_handle(buffer, fd)\n        .cast::<HANDLE>()\n        .read_unaligned(),\n      &mut handle,\n    )\n  };\n  handle\n}\n\npub unsafe fn uv_duplicate_handle(\n  handle: HANDLE,\n) -> Result<HANDLE, std::io::Error> {\n  if handle == INVALID_HANDLE_VALUE\n    || handle.is_null()\n    || handle == ((-2i32) as usize as HANDLE)\n  {\n    return Err(std::io::Error::new(\n      std::io::ErrorKind::InvalidInput,\n      \"Invalid handle\",\n    ));\n  }\n\n  let mut dup = INVALID_HANDLE_VALUE;\n  let current_process = unsafe { GetCurrentProcess() };\n\n  if unsafe {\n    DuplicateHandle(\n      current_process,\n      handle,\n      current_process,\n      &mut dup,\n      0,\n      1,\n      DUPLICATE_SAME_ACCESS,\n    )","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/runtime/subprocess_windows/src/process_stdio.rs#L156-L192","documentation":"During spawn, each stdio slot carrying a raw handle is duplicated into the child with DuplicateHandle. uv_duplicate_handle() first rejects obviously broken values - INVALID_HANDLE_VALUE (-1), NULL, and the -2 sentinel - with InvalidInput 'Invalid handle', because duplicating them would fail or hand the child a garbage stream.","triggerScenarios":"Passing a closed, null, or sentinel handle in the stdio vector of a spawn: a resource already closed before spawn, an fd of -1 or 0 coming from config defaults, or code that treats Unix fd numbers as Windows handles.","commonSituations":"Forwarding request/server streams or inherited fds that were closed before the child started; mixing libuv handle values with plain integers; sanitization code that substitutes unknown fds with -1.","solutions":["Use supported stdio actions (\"pipe\", \"inherit\", \"null\") instead of raw handles","Ensure any stream or resource passed via stdio is still open at spawn time","Validate handles are not null, -1, or -2 before building the stdio vector"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isValidHandle(h: number | null): boolean {\n  return typeof h === \"number\" && h !== 0 && h !== -1 && h !== -2;\n}\n// validate every raw stdio handle before building the spawn options","typeGuard":"const isValidRawHandle = (h: unknown): h is number =>\n  typeof h === \"number\" && h !== 0 && h !== -1 && h !== -2;","tryCatchPattern":null,"preventionTips":["Prefer stdio actions (\"pipe\"/\"inherit\"/\"null\") over raw handles","Spawn immediately after acquiring streams, before anything can close them","Never substitute sentinel values (-1/0) for unknown fds in stdio config"],"tags":["windows","subprocess","stdio","file-descriptor","invalid-handle"],"backgroundTag":"invalid-file-descriptor","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}