EpicGames/lore · error · io::Error
Pager process stdin not available
Error message
Pager process stdin not available
What it means
`PagerProcess::stdin` returns this io::Error (ErrorKind::NotFound) when the pager child process has no piped stdin. `PagerProcess::new` only spawns a pager when stdout is a terminal and a pager command is configured and spawnable; otherwise the PagerProcess is created without a usable stdin, and any `write`/`flush` (via the `Write` impl) or direct `stdin()` call fails.
Solutions
- Check whether output is going to a terminal (e.g. `stdout().is_terminal()`) and fall back to writing to plain stdout instead of the pager when it is not.
- Verify the `pager` setting in the client config names an installed pager binary (e.g. `less`); an empty or broken value leaves no stdin.
- Handle the write error gracefully by writing to a backup stream (use `Pager::with_backup_stream`).
Example fix
// before
pager.write_all(output)?; // fails when no pager spawned
// after
if stdout().is_terminal() {
pager.write_all(output)?;
} else {
stdout().write_all(output)?;
} Defensive patterns
Strategy: fallback
Validate before calling
// Rust: only use the pager when stdout is a terminal and a pager command is configured
let use_pager = std::io::stdout().is_terminal()
&& config.pager.split_ascii_whitespace().next().is_some(); Try / catch
// Rust
use std::io::Write;
match pager.write_all(bytes) {
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
// pager has no stdin (no TTY / spawn failed): write to backup stream
backup.write_all(bytes)?;
}
r => r?,
} Prevention
- Always construct the pager via `Pager::with_backup_stream` so failed pager writes go to plain output.
- Check `stdout().is_terminal()` before instantiating the pager.
- Validate the configured pager command exists (e.g. `which $PAGER`) in diagnostics.
When it happens
Trigger: Calling `write` or `flush` on a `PagerProcess` (or `stdin()` directly) after the pager was created without piped stdin — i.e. stdout was not a terminal, the configured pager string was empty, or `Command::spawn` failed so no child with piped stdin exists.
Common situations: Running a lore-client command with output piped to another process or to a file (stdout not a TTY), so no pager is spawned but code still writes to the pager; an invalid or missing pager binary in the config's `pager` setting so spawn silently failed.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- bytes exceeds the byte whole-file limit; open the file and…
- unsupported LORE_IO_BACKEND
- file ended before the requested read length
- file refused further writes
- file ended before the requested read length
AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13).
Data as JSON: /api/errors/87cba03dfe5f5e50.
Report an issue: GitHub.
Appendix: source
Thrown at lore-client/src/cli/pager.rs:88
} else {
let config = config();
let mut pager_config = config.pager.split_ascii_whitespace();
if let Some(pager_target) = pager_config.next() {
let mut cmd = Command::new(pager_target);
cmd.args(pager_config);
Some(cmd)
} else {
None
}
.and_then(|mut cmd| cmd.stdin(Stdio::piped()).spawn().ok())
};
child.map(|child| PagerProcess { child })
}
fn stdin(&self) -> std::io::Result<&ChildStdin> {
match &self.child.stdin {
None => Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Pager process stdin not available",
)),
Some(stdin) => Ok(stdin),
}
}
}
impl Write for PagerProcess {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.stdin()?.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.stdin()?.flush()
}
}
View on GitHub (pinned to 074eb0b0d1)