atuinsh/atuin · error · std::io::Error
Interactive mode requires a terminal
Error message
Interactive mode requires a terminal
What it means
Returned by TerminalWriter::new in interactive search when Atuin is compiled for a target that is neither unix nor windows (the #[cfg(not(any(unix, windows)))] arm at interactive.rs:1466). Interactive mode needs a terminal: stdout when it is a TTY, /dev/tty on unix, or CONOUT$ on Windows; with no platform backend available it fails with io::ErrorKind::Unsupported. This is effectively a build/platform configuration problem, not a runtime environment one.
Source
Thrown at crates/atuin/src/command/client/search/interactive.rs:1467
.read(true)
.write(true)
.open("CONOUT$")?;
let initial_console_output_cp = unsafe { GetConsoleOutputCP() };
if initial_console_output_cp != Self::CP_UTF8 {
unsafe {
SetConsoleOutputCP(Self::CP_UTF8);
}
}
Ok(TerminalWriter::ConOut(
std::io::LineWriter::new(file),
initial_console_output_cp,
))
}
#[cfg(not(any(unix, windows)))]
Err(std::io::Error::new(
std::io::ErrorKind::Unsupported,
"Interactive mode requires a terminal",
))
}
}
impl Write for TerminalWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
match self {
TerminalWriter::Stdout(stdout) => stdout.write(buf),
#[cfg(unix)]
TerminalWriter::Tty(file) => file.write(buf),
#[cfg(windows)]
TerminalWriter::ConOut(writer, _) => writer.write(buf),
}
}
fn flush(&mut self) -> std::io::Result<()> {View on GitHub (pinned to 202f6ad98e)
Solutions
- Run interactive search on a supported platform (unix or windows builds of Atuin)
- Use non-interactive search (`atuin search <query>`) which prints results to stdout and never builds a TerminalWriter
- If porting, implement a TerminalWriter backend for the target (e.g. open the platform's controlling terminal) behind a new cfg gate
- Catch io::ErrorKind::Unsupported in embedding code and degrade to non-interactive output
Example fix
// before
let writer = TerminalWriter::new()?;
// after
let writer = TerminalWriter::new().or_else(|e| {
if e.kind() == std::io::ErrorKind::Unsupported {
// fall back to non-interactive output on this platform
}
Err(e)
})?; Defensive patterns
Strategy: fallback
Validate before calling
// Detect the unsupported case before launching the TUI
let interactive_ok = cfg!(any(unix, windows));
if !interactive_ok { /* run non-interactive search path instead */ } Try / catch
match TerminalWriter::new() {
Ok(w) => { /* run TUI */ }
Err(e) if e.kind() == std::io::ErrorKind::Unsupported => {
// no terminal backend on this platform: fall back to plain output
}
Err(e) => return Err(e.into()),
} Prevention
- Only target unix or windows platforms when you need interactive search
- In scripts and embeddings, prefer non-interactive `atuin search <query>`
- Gate interactive mode behind a cfg!(any(unix, windows)) check in porting efforts
- Contribute a TerminalWriter backend before shipping a new platform build
When it happens
Trigger: Building the atuin binary for an exotic target (wasm32, redox, etc.) where none of the cfg(unix)/cfg(windows) terminal backends compile, then invoking `atuin search -i` (interactive mode), which constructs TerminalWriter.
Common situations: Cross-compiling Atuin to a Tier-3 target; running in a sandbox/wasm environment that maps neither unix nor windows cfg flags; developers porting Atuin hitting the compile-time gap during first run on a new OS.
Related errors
- Failed to get current PID
- Empty theme directory override and could not find theme else
- Failed to deserialize theme: {}
- Parent requested but we hit the recursion limit
- key file vanished immediately after a concurrent write
AI-assisted analysis of atuinsh/atuin@202f6ad98e (2026-08-16).
Data as JSON: /api/errors/6499ff40fa42df31.
Report an issue: GitHub.