{"record":{"id":"07e2daeecdc51a00","repo":"sinelaw/fresh","slug":"failed-to-duplicate-stdin-handle","errorCode":null,"errorMessage":"Failed to duplicate stdin handle: {}","messagePattern":"Failed to duplicate stdin handle: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-editor/src/main.rs","lineNumber":769,"sourceCode":"    }\n\n    let mut duplicated: HANDLE = std::ptr::null_mut();\n    // SAFETY: duplicating a handle this process owns into this process; the\n    // result is checked and then owned by the `File` below.\n    let ok = unsafe {\n        let me = GetCurrentProcess();\n        DuplicateHandle(\n            me,\n            stdin_handle,\n            me,\n            &mut duplicated,\n            0,\n            0, // not inheritable\n            DUPLICATE_SAME_ACCESS,\n        )\n    };\n    if ok == 0 {\n        anyhow::bail!(\n            \"Failed to duplicate stdin handle: {}\",\n            io::Error::last_os_error()\n        );\n    }\n\n    // SAFETY: `duplicated` is a valid handle this function just created and\n    // hands sole ownership of to the returned `File`.\n    Ok(unsafe { std::fs::File::from_raw_handle(duplicated.cast()) })\n}\n\n/// Check if stdin has data available (is a pipe or redirect, not a TTY)\nfn stdin_has_data() -> bool {\n    use std::io::IsTerminal;\n    !io::stdin().is_terminal()\n}\n\n/// Reopen stdin from /dev/tty after reading piped content.\n/// This allows crossterm to use the terminal for keyboard input","sourceCodeStart":751,"sourceCodeEnd":787,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/src/main.rs#L751-L787","documentation":"DuplicateHandle failed while duplicating the process's stdin handle (needed so a File can safely own it). The error message carries io::Error::last_os_error() describing the underlying Win32 failure. Without a duplicated handle the editor cannot reassign stdin.","triggerScenarios":"Calling DuplicateHandle with the current process pseudo-handle on the stdin handle returns 0 — e.g. the source handle was already closed/invalid, or a privilege/handle-type issue prevents duplication.","commonSituations":"stdin handle closed by a parent process or wrapper script; racing close between GetStdHandle and DuplicateHandle; running inside a sandbox that restricts handle duplication.","solutions":["Verify the stdin handle is still valid right before duplicating; re-fetch it if necessary","Ensure DUPLICATE_SAME_ACCESS and non-inheritable flags are correct and buffers/pointers are valid","Check whether an antivirus/sandbox is interfering with handle duplication","Fall back to opening CONIN$ directly instead of duplicating the existing stdin"],"exampleFix":"// before\nlet ok = unsafe { DuplicateHandle(GetCurrentProcess(), stdin_handle, GetCurrentProcess(), &mut duplicated, 0, 0, DUPLICATE_SAME_ACCESS) };\nif ok == 0 { anyhow::bail!(\"Failed to duplicate stdin handle: {}\", io::Error::last_os_error()); }\n// after\nlet stdin_handle = unsafe { GetStdHandle(STD_INPUT_HANDLE) };\nif stdin_handle == INVALID_HANDLE_VALUE || stdin_handle.is_null() {\n    anyhow::bail!(\"stdin handle unavailable; cannot duplicate\");\n}\nlet ok = unsafe { DuplicateHandle(GetCurrentProcess(), stdin_handle, GetCurrentProcess(), &mut duplicated, 0, 0, DUPLICATE_SAME_ACCESS) };\nif ok == 0 { anyhow::bail!(\"Failed to duplicate stdin handle: {}\", io::Error::last_os_error()); }","handlingStrategy":"try-catch","validationCode":"let h = unsafe { GetStdHandle(STD_INPUT_HANDLE) };\nif h == INVALID_HANDLE_VALUE || h.is_null() { eprintln!(\"stdin invalid; skip duplicate\"); }","typeGuard":"fn duplicatable(h: HANDLE) -> bool { !h.is_null() && h != INVALID_HANDLE_VALUE }","tryCatchPattern":"if let Err(e) = duplicate_stdin() {\n    eprintln!(\"handle duplication failed: {e}; falling back to CONIN$\");\n}","preventionTips":["Re-fetch the stdin handle immediately before duplication","Do not close stdin in parent/spawner code before the child initializes","Test under sandbox/AV configurations that may block DuplicateHandle"],"tags":["windows","handle","stdin"],"backgroundTag":"file-open-failed","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}