rtk-ai/rtk · error

Failed to read stdin

Error message

Failed to read stdin: {}

What it means

In non-passthrough mode, `pipe_cmd::run` reads up to RAW_CAP+1 bytes from stdin via `Read::take(...).read_to_string(&mut buf)`. Two failure modes surface here: the read itself errors (mapped to `Failed to read stdin: {}` at line 267), and, if more than RAW_CAP bytes arrived, a subsequent `bail!("stdin exceeds {} byte limit", RAW_CAP)` protects rtk from oversized payloads. Both exist because pipe filters operate on bounded in-memory buffers.

Solutions

  1. Ensure input is valid UTF-8 text (e.g. `iconv -f ... -t utf-8` first) — read_to_string fails on invalid bytes.
  2. Reduce input below rtk's stdin size cap: pre-filter/truncate with `head -c`, or use `rtk proxy` for unbounded raw output.
  3. Verify the stdin source is readable (`test -r file` before redirecting) and not a device that errors on read.
  4. If the size limit is the blocker, split input into chunks or process with standard tools instead of `rtk pipe`.

Example fix

// before (shell)
cat binary.dump | rtk pipe --filter text

// after (shell)
# decode to UTF-8 and cap size before piping
iconv -f latin1 -t utf-8 binary.dump | head -c 1048576 | rtk pipe --filter text
Defensive patterns

Strategy: validation

Validate before calling

# check size and UTF-8 before piping into rtk pipe
size=$(stat -c%s input.txt)
limit=1048576  # match rtk's RAW_CAP
if [ "$size" -gt "$limit" ]; then echo "input too large for rtk pipe" >&2; exit 1; fi
iconv -f utf-8 -t utf-8 input.txt >/dev/null 2>&1 || { echo "input is not valid UTF-8" >&2; exit 1; }

Try / catch

if ! rtk pipe --filter text < input.txt; then
  echo 'fell back: use rtk proxy or split the input' >&2
  rtk proxy cat input.txt
fi

Prevention

When it happens

Trigger: Piping data into `rtk pipe` (without --passthrough) when: (a) stdin read fails (invalid UTF-8 for read_to_string, or an I/O error) → this message; (b) input exceeds the RAW_CAP byte cap → the adjacent size-limit bail. Raised from `pipe_cmd::run` at src/cmds/system/pipe_cmd.rs:267.

Common situations: Piping binary data (non-UTF-8) into `rtk pipe`; piping very large files/logs that exceed rtk's stdin byte cap; stdin from a special file or device that errors mid-read; encoding mismatches after locale changes.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of rtk-ai/rtk@0924356b4c (2026-09-19). Data as JSON: /api/errors/229f9a4cee75fd30. Report an issue: GitHub.

Appendix: source

Thrown at src/cmds/system/pipe_cmd.rs:267

        |_| {
            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, \
                 paratest, php-test, ecs, phpstan, pint",
                name
            )
        })?,
        None => auto_detect_filter(&buf),
    };

    let output = apply_filter(filter_fn, &buf);

View on GitHub (pinned to 0924356b4c)