sinelaw/fresh · error
Failed to set stdin to CONIN$
Error message
Failed to set stdin to CONIN$: {} What it means
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.
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
Example fix
// before
let success = unsafe { SetStdHandle(STD_INPUT_HANDLE, conin_handle) };
if success == 0 { anyhow::bail!("Failed to set stdin to CONIN$: {}", io::Error::last_os_error()); }
// after
let success = unsafe { SetStdHandle(STD_INPUT_HANDLE, conin_handle) };
if success == 0 {
eprintln!("SetStdHandle failed ({}); using CONIN$ handle directly", io::Error::last_os_error());
stdin_for_reads = Some(conin_handle); // fallback path
} Defensive patterns
Strategy: retry
Validate before calling
let conin = open_conin()?; // ensure the open succeeded before SetStdHandle
Try / catch
if unsafe { SetStdHandle(STD_INPUT_HANDLE, conin) } == 0 {
eprintln!("SetStdHandle failed: {}", io::Error::last_os_error());
// fall back to using the handle directly
} Prevention
- 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
When it happens
Trigger: SetStdHandle(STD_INPUT_HANDLE, conin_handle) returns 0 — rare Win32 failure while replacing the process's stdin handle slot.
Common situations: Corrupted process handle table, conflicting handle redirections done by the spawning process, or an antivirus/security product intercepting handle manipulation.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- Failed to get stdin handle
- Failed to duplicate stdin handle
- Failed to open CONIN$
- io::Error::last_os_error()
- No data piped to stdin
AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13).
Data as JSON: /api/errors/5ee0522e27926546.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-editor/src/main.rs:841
CreateFileW(
conin.as_ptr(),
FILE_GENERIC_READ,
FILE_SHARE_READ,
std::ptr::null(),
OPEN_EXISTING,
0,
std::ptr::null_mut(),
)
};
if conin_handle == INVALID_HANDLE_VALUE {
anyhow::bail!("Failed to open CONIN$: {}", io::Error::last_os_error());
}
// Replace stdin with the console input handle
let success = unsafe { SetStdHandle(STD_INPUT_HANDLE, conin_handle) };
if success == 0 {
anyhow::bail!(
"Failed to set stdin to CONIN$: {}",
io::Error::last_os_error()
);
}
Ok(())
}
fn handle_first_run_setup(
editor: &mut Editor,
args: &Args,
file_locations: &[FileLocation],
show_file_explorer: bool,
stdin_stream: &mut Option<StdinStreamState>,
workspace_enabled: bool,
) -> AnyhowResult<()> {
if let Some(log_path) = &args.event_log {
tracing::trace!("Event logging enabled: {}", log_path.display());View on GitHub (pinned to 67894ca546)