{"record":{"id":"5ee0522e27926546","repo":"sinelaw/fresh","slug":"failed-to-set-stdin-to-conin","errorCode":null,"errorMessage":"Failed to set stdin to CONIN$: {}","messagePattern":"Failed to set stdin to CONIN\\$: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-editor/src/main.rs","lineNumber":841,"sourceCode":"        CreateFileW(\n            conin.as_ptr(),\n            FILE_GENERIC_READ,\n            FILE_SHARE_READ,\n            std::ptr::null(),\n            OPEN_EXISTING,\n            0,\n            std::ptr::null_mut(),\n        )\n    };\n\n    if conin_handle == INVALID_HANDLE_VALUE {\n        anyhow::bail!(\"Failed to open CONIN$: {}\", io::Error::last_os_error());\n    }\n\n    // Replace stdin with the console input handle\n    let success = unsafe { SetStdHandle(STD_INPUT_HANDLE, conin_handle) };\n    if success == 0 {\n        anyhow::bail!(\n            \"Failed to set stdin to CONIN$: {}\",\n            io::Error::last_os_error()\n        );\n    }\n\n    Ok(())\n}\n\nfn handle_first_run_setup(\n    editor: &mut Editor,\n    args: &Args,\n    file_locations: &[FileLocation],\n    show_file_explorer: bool,\n    stdin_stream: &mut Option<StdinStreamState>,\n    workspace_enabled: bool,\n) -> AnyhowResult<()> {\n    if let Some(log_path) = &args.event_log {\n        tracing::trace!(\"Event logging enabled: {}\", log_path.display());","sourceCodeStart":823,"sourceCodeEnd":859,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/src/main.rs#L823-L859","documentation":"After successfully opening CONIN$, the editor calls SetStdHandle(STD_INPUT_HANDLE, conin_handle) to make it the process stdin. A zero return means the swap failed and the last OS error is reported. stdin remains pointing at its previous (possibly non-interactive) source.","triggerScenarios":"SetStdHandle(STD_INPUT_HANDLE, conin_handle) returns 0 — rare Win32 failure while replacing the process's stdin handle slot.","commonSituations":"Corrupted process handle table, conflicting handle redirections done by the spawning process, or an antivirus/security product intercepting handle manipulation.","solutions":["Retry the SetStdHandle call once and re-check with GetLastError","Fall back to using the opened CONIN$ handle directly for reads instead of swapping the std handle","Verify no concurrent thread is mutating std handles during startup","Log last_os_error to identify the specific Win32 failure and adjust spawning accordingly"],"exampleFix":"// before\nlet success = unsafe { SetStdHandle(STD_INPUT_HANDLE, conin_handle) };\nif success == 0 { anyhow::bail!(\"Failed to set stdin to CONIN$: {}\", io::Error::last_os_error()); }\n// after\nlet success = unsafe { SetStdHandle(STD_INPUT_HANDLE, conin_handle) };\nif success == 0 {\n    eprintln!(\"SetStdHandle failed ({}); using CONIN$ handle directly\", io::Error::last_os_error());\n    stdin_for_reads = Some(conin_handle); // fallback path\n}","handlingStrategy":"retry","validationCode":"let conin = open_conin()?; // ensure the open succeeded before SetStdHandle","typeGuard":null,"tryCatchPattern":"if unsafe { SetStdHandle(STD_INPUT_HANDLE, conin) } == 0 {\n    eprintln!(\"SetStdHandle failed: {}\", io::Error::last_os_error());\n    // fall back to using the handle directly\n}","preventionTips":["Avoid concurrent std-handle mutation during startup","Test under security software that hooks handle APIs","Prefer reading via the opened CONIN$ handle over swapping std handles when possible"],"tags":["windows","console","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"}