sinelaw/fresh · error
Failed to open CONIN$
Error message
Failed to open CONIN$: {} What it means
On Windows, the editor opens CONIN$ (the console input device) with CreateFileW to use as a fresh stdin source. If CreateFileW returns INVALID_HANDLE_VALUE the OS error is reported. This happens when no console is attached to the process or access to the console device is denied.
Solutions
- Run the editor from a console session (cmd/Windows Terminal) so CONIN$ exists
- Allocate a console first with AllocConsole or attach to the parent's console with AttachConsole(ATTACH_PARENT_PROCESS)
- For ssh scenarios, request a PTY/pseudo-terminal allocation (ssh -t)
- Check the reported last_os_error for access-denied and adjust how the process is spawned
Example fix
// before
let conin_handle = unsafe { CreateFileW(CONIN$, GENERIC_READ|GENERIC_WRITE, SHARE_RW, null, OPEN_EXISTING, 0, null_mut()) };
// after
unsafe { AllocConsole(); } // ensure a console exists before opening CONIN$
let conin_handle = unsafe { CreateFileW(CONIN$, GENERIC_READ|GENERIC_WRITE, SHARE_RW, null, OPEN_EXISTING, 0, null_mut()) };
if conin_handle == INVALID_HANDLE_VALUE {
anyhow::bail!("Failed to open CONIN$: {}", io::Error::last_os_error());
} Defensive patterns
Strategy: fallback
Validate before calling
fn console_attached() -> bool {
unsafe { GetConsoleWindow() != std::ptr::null_mut() }
} Type guard
fn is_valid_handle(h: HANDLE) -> bool { h != INVALID_HANDLE_VALUE && !h.is_null() } Try / catch
match open_conin() {
Ok(h) => use_conin(h),
Err(e) => { unsafe { AllocConsole(); } retry_or_report(e) }
} Prevention
- Attach or allocate a console (AttachConsole/AllocConsole) before console I/O
- For ssh use PTY allocation (ssh -t)
- Launch from cmd/Windows Terminal rather than GUI launchers
When it happens
Trigger: CreateFileW("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, security_attributes, OPEN_EXISTING, 0, null) returns INVALID_HANDLE_VALUE — typically when the process has no attached console.
Common situations: Launching the editor from a GUI/launcher without a console, from a Windows service, or in an environment where console devices are unavailable (some ssh sessions without terminal allocation).
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
AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13).
Data as JSON: /api/errors/efd537c931a7a054.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-editor/src/main.rs:835
// "CONIN$" is the console input device on Windows
// This is analogous to /dev/tty on Unix
let conin: Vec<u16> = "CONIN$\0".encode_utf16().collect();
let conin_handle = unsafe {
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],View on GitHub (pinned to 67894ca546)