Hmbown/CodeWhale · error
read-only pipelines require bash or zsh; run each read…
Error message
read-only pipelines require bash or zsh; run each read separately
What it means
The agent read-only shell pipeline path in crates/tui/src/tools/shell.rs only supports bash and zsh. When it inspects the invoking shell (e.g. via $SHELL) and finds any other name, it refuses to execute the pipeline as a single read-only command. This prevents reinterpreting shell-specific pipeline syntax under a shell whose semantics the read-only policy was not validated against.
Solutions
- Set your SHELL environment variable (or the tool's shell configuration) to /bin/bash or /usr/bin/zsh before invoking the agent.
- Split the pipeline into separate single read-only commands and run each one individually, as the message suggests.
- On minimal containers, install bash or create a symlink so a bash binary is available and selected.
Example fix
// before $ SHELL=/bin/sh codewhale agent: git log | head -20 // after $ SHELL=/bin/bash codewhale agent: git log | head -20 // or split agent: git log -20 # run separately instead of piping to head
Defensive patterns
Strategy: validation
Validate before calling
const shell = process.env.SHELL ?? '';
const base = shell.split('/').pop() ?? '';
if (base !== 'bash' && base !== 'zsh') {
// run each read command separately instead of a pipeline
} Type guard
function isSupportedShell(shell: string | undefined): boolean {
const base = (shell ?? '').split('/').pop();
return base === 'bash' || base === 'zsh';
} Prevention
- Launch the agent with SHELL=/bin/bash (or zsh) in containers and CI.
- Avoid login shells like fish/dash when using the agent's pipeline reads.
- Prefer single non-piped read commands when shell support is uncertain.
When it happens
Trigger: Calling the agent read-only pipeline execution path with a command while the detected shell program is not 'bash' or 'zsh' (e.g. sh, dash, fish, nushell, pwsh, cmd, or an unset/non-UTF-8 SHELL that fails the Some("bash" | "zsh") match).
Common situations: Running Codewhale on systems where /bin/sh links to dash (Debian/Ubuntu) and SHELL is inherited as 'sh'; users whose login shell is fish, zsh-less minimal containers, or Windows where the command would run under cmd/powershell.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- classifier-approved read command was empty
- could not parse classifier-approved read command
- pipeline contains a command outside the read-only policy
- agent profile may not request allow_shell=true
- allowlisted read-only executable
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/8bbdac5265d9fc16.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/shell.rs:4157
.and_then(serde_json::Value::as_str)
.is_some()
}
fn hardened_readonly_pipeline(command: &str, workspace: &std::path::Path) -> Result<String> {
use crate::shell_dispatcher::ShellKind;
// POSIX quoting must never be passed to a different command interpreter.
let supported = match crate::shell_dispatcher::global_dispatcher().kind() {
ShellKind::Bash => true,
ShellKind::Custom { binary, .. } => matches!(
std::path::Path::new(binary)
.file_name()
.and_then(|name| name.to_str()),
Some("bash" | "zsh")
),
_ => false,
};
if !supported {
return Err(anyhow!(
"read-only pipelines require bash or zsh; run each read separately"
));
}
if !is_agent_readonly_shell_command(command) {
return Err(anyhow!(
"pipeline contains a command outside the read-only policy"
));
}
let segments = command
.split('|')
.map(|segment| {
let (program, args) = hardened_readonly_argv(segment)?;
let program = resolve_readonly_program(&program, workspace)?;
let program = program
.to_str()
.ok_or_else(|| anyhow!("read-only executable path is not valid UTF-8"))?;
Ok(std::iter::once(program)
.chain(args.iter().map(String::as_str))View on GitHub (pinned to 73e0f67d83)