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

  1. 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.
  2. Verify the `pager` setting in the client config names an installed pager binary (e.g. `less`); an empty or broken value leaves no stdin.
  3. 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

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


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)