rtk-ai/rtk · error

stdout streaming thread panicked

Error message

stdout streaming thread panicked

What it means

In proxy mode rtk spawns capture threads for the child's stdout/stderr and joins them after wait(). If the stdout reader thread panics, join() returns Err and rtk converts it to this anyhow error instead of deadlocking or emitting partial output. It signals an internal defect or extreme edge (e.g. a capture-loop bug on very large output), not a property of the wrapped command — the child's exit status was already collected.

Source

Thrown at src/main.rs:2674

                    }
                    let mut err = std::io::stderr().lock();
                    err.write_all(&buf[..count])?;
                    err.flush()?;
                }

                Ok(captured)
            });

            let status = child
                .0
                .take()
                .context("Child process missing")?
                .wait()
                .context(format!("Failed waiting for command: {}", cmd_name))?;

            let stdout_bytes = stdout_handle
                .join()
                .map_err(|_| anyhow::anyhow!("stdout streaming thread panicked"))??;
            let stderr_bytes = stderr_handle
                .join()
                .map_err(|_| anyhow::anyhow!("stderr streaming thread panicked"))??;

            let stdout = String::from_utf8_lossy(&stdout_bytes);
            let stderr = String::from_utf8_lossy(&stderr_bytes);
            let full_output = format!("{}{}", stdout, stderr);

            // Track usage (input = output since no filtering)
            timer.track(
                &format!("{} {}", cmd_name, cmd_args.join(" ")),
                &format!("rtk proxy {} {}", cmd_name, cmd_args.join(" ")),
                &full_output,
                &full_output,
            );

            core::utils::exit_code_from_status(&status, &cmd_name)
        }

View on GitHub (pinned to d977e1c316)

Solutions

  1. Re-run the command without rtk (`git log --oneline -20`) — the wrapped command itself did not fail
  2. Reproduce and gather evidence: `rtk --version` plus the exact command and output size, ideally with a backtrace (RUST_BACKTRACE=1)
  3. Update rtk to the latest release (or build from main) and report the panic at the rtk-ai/rtk issue tracker if it persists

Example fix

# before
rtk proxy npm run build   # internal stdout thread panic

# after (fallback: direct execution; you lose tracking, not the build)
npm run build
Defensive patterns

Strategy: fallback

Validate before calling

# bash: fall back to direct execution when rtk itself fails
if ! rtk proxy "$@"; then
  echo 'rtk proxy failed — running command directly' >&2
  exec "$@"
fi

Try / catch

# bash: wrap rtk proxy so tooling never hard-depends on it
if ! out=$(rtk proxy "$@" 2>&1); then
  echo "rtk proxy internal failure ($?), falling back" >&2
  "$@"
else
  printf '%s\n' "$out"
fi

Prevention

When it happens

Trigger: A panic inside the stdout capture thread while proxying output-heavy commands (`rtk proxy cat huge.log`, `rtk proxy npm install` in a big monorepo) — src/main.rs:2676.

Common situations: Very large outputs or unusual pipe conditions hitting a bug in the installed rtk version; rare in practice.

Related errors


AI-assisted analysis of rtk-ai/rtk@d977e1c316 (2026-08-16). Data as JSON: /api/errors/d43c6c66c8b6acc1. Report an issue: GitHub.