rtk-ai/rtk · error
Failed to relay stdin
Error message
Failed to relay stdin: {} What it means
`rtk pipe` (with passthrough mode) relays everything from stdin to stdout using `std::io::copy`. If the copy from stdin fails — broken pipe on stdout, I/O error on the input descriptor — pipe_cmd.rs:259 wraps the io::Error into `anyhow!("Failed to relay stdin: {}", e)`. It signals that raw stdin relaying was interrupted by an OS-level I/O failure.
Solutions
- Ensure the downstream consumer reads all input before exiting (avoid `| head` truncation), or tolerate the error as expected SIGPIPE behavior.
- Check that stdin is a readable, valid source (not a closed/unusable descriptor) before invoking `rtk pipe --passthrough`.
- Retry the pipeline; if it persists without a downstream early-exit, inspect disk/terminal health and report an rtk bug.
Example fix
// before (shell) cat big.log | rtk pipe --passthrough | head -n 5 // after (shell) cat big.log | rtk pipe --passthrough | sed -n '1,5p;$p' // or capture full output before truncating rtk pipe --passthrough < big.log > out.txt && head -n 5 out.txt
Defensive patterns
Strategy: try-catch
Validate before calling
# ensure downstream consumer will keep reading command -v head >/dev/null && echo 'avoid early-exiting consumers like `| head`'
Try / catch
if ! cat data | rtk pipe --passthrough > out.txt 2>err.txt; then grep -q 'Failed to relay stdin' err.txt && echo 'downstream closed early; retry without truncation' fi
Prevention
- Do not pipe into consumers that exit early (`head`, `timeout`) in passthrough mode.
- Keep terminal/SSH sessions alive during long relays.
- Redirect to a file when downstream truncation is likely.
When it happens
Trigger: Calling `rtk pipe --passthrough` (passthrough=true) while `std::io::copy(&mut stdin, &mut stdout)` fails: stdout consumer has exited/closed the pipe (EPIPE), or reading stdin hits an I/O error. Raised from `pipe_cmd::run` at src/cmds/system/pipe_cmd.rs:259.
Common situations: Piping into `rtk pipe --passthrough | head -n1` so head closes the pipe early; terminal/SSH session disconnecting mid-stream; redirected stdin from a file or device that errors during read.
Related errors
AI-assisted analysis of rtk-ai/rtk@0924356b4c (2026-09-19).
Data as JSON: /api/errors/bad2ea4e8522b017.
Report an issue: GitHub.
Appendix: source
Thrown at src/cmds/system/pipe_cmd.rs:259
}
fn identity_filter(input: &str) -> String {
input.to_string()
}
fn apply_filter(filter_fn: fn(&str) -> String, input: &str) -> String {
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| filter_fn(input))).unwrap_or_else(
|_| {
eprintln!("[rtk] warning: filter panicked — passing through raw output");
input.to_string()
},
)
}
pub fn run(filter_name: Option<&str>, passthrough: bool) -> Result<()> {
if passthrough {
std::io::copy(&mut std::io::stdin(), &mut std::io::stdout())
.map_err(|e| anyhow::anyhow!("Failed to relay stdin: {}", e))?;
return Ok(());
}
let mut buf = String::new();
std::io::stdin()
.take((RAW_CAP + 1) as u64)
.read_to_string(&mut buf)
.map_err(|e| anyhow::anyhow!("Failed to read stdin: {}", e))?;
if buf.len() > RAW_CAP {
anyhow::bail!("stdin exceeds {} byte limit", RAW_CAP);
}
let filter_fn = match filter_name {
Some(name) => resolve_filter(name).ok_or_else(|| {
anyhow::anyhow!(
"Unknown filter '{}'. Available: cargo-test, pytest, go-test, go-build, \
ctest, tsc, vitest, grep, rg, find, fd, git-log, git-diff, git-status, \
log, mypy, ruff-check, ruff-format, sqlfluff-lint, prettier, phpunit, pest, \View on GitHub (pinned to 0924356b4c)