Hmbown/CodeWhale · error
classifier-approved Git read did not keep its subcommand in…
Error message
classifier-approved Git read did not keep its subcommand in argv[1]
What it means
This error is raised in `hardened_readonly_argv` when the subcommand found after the `--no-pager`/`-C` preamble is not one of the hardener-supported read-only subcommands (diff, log, show, status, ls-files, blame, grep). The guard enforces that only allowlisted Git reads, whose safety flags the hardener knows how to splice in, reach execution; anything else is rejected instead of run unhardened.
Solutions
- Use one of the supported read-only subcommands: diff, log, show, status, ls-files, blame, grep
- For other Git reads, fall back to the non-hardened (permission-prompted) shell path or another tool
- If a new subcommand should be supported, add it to the match in hardened_readonly_argv together with the hardening flags it needs
Example fix
// before
run_readonly("git remote -v")
// after
run_readonly("git ls-files") // or use the standard permissioned shell path Defensive patterns
Strategy: validation
Validate before calling
const GIT_READONLY_SUBCOMMANDS: &[&str] =
&["diff", "log", "show", "status", "ls-files", "blame", "grep"];
fn git_subcommand_allowed(cmd: &str) -> bool {
let argv = shell_words::split(cmd).unwrap_or_default();
let mut i = 1;
while matches!(argv.get(i).map(String::as_str), Some("--no-pager") | Some("-C")) {
i += if argv.get(i).map(String::as_str) == Some("-C") { 2 } else { 1 };
}
matches!(argv.get(i).map(String::as_str), Some(s) if GIT_READONLY_SUBCOMMANDS.contains(&s))
} Prevention
- Restrict read-only Git usage to diff/log/show/status/ls-files/blame/grep
- Check the hardener's allowlist before adding new Git invocations to agent prompts
- Route other Git reads through the permission-prompted shell path
When it happens
Trigger: Issuing a classifier-approved read-only `git` command whose subcommand is outside the allowlist, e.g. `git fetch`, `git remote -v`, `git add -n`, or `git worktree list`. The classifier may have passed the command as a read, but the argv hardener independently rejects unsupported subcommands.
Common situations: Developers assuming any read-looking Git command is allowed (`git remote -v`, `git branch -a`, `git config --get`); version drift where the classifier allowlist and the hardener's match arm diverge; typos in the subcommand token.
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 Git read was missing its literal…
- read-only command must name a bare allowlisted executable
- allowlisted read-only executable
- no trusted executable search path remains outside the…
- pipeline contains a command outside the read-only policy
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/2e9502c36bfd8ace.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/shell.rs:4236
argv.splice(
at..at,
["--no-ext-diff".to_string(), "--no-textconv".to_string()],
);
}
"log" | "show" => {
let at = subcommand_index + 1;
argv.splice(
at..at,
[
"--no-ext-diff".to_string(),
"--no-textconv".to_string(),
"--no-show-signature".to_string(),
],
);
}
"status" | "ls-files" | "blame" | "grep" => {}
_ => {
return Err(anyhow!(
"classifier-approved Git read did not keep its subcommand in argv[1]"
));
}
}
}
let program = argv.remove(0);
Ok((program, argv))
}
fn enforce_readonly_workspace_operands(
command: &str,
workspace: &std::path::Path,
effective_cwd: &std::path::Path,
) -> Result<(), ToolError> {
let argv = shell_words::split(&normalize_windows_command_paths(command)).map_err(|error| {
ToolError::invalid_input(format!(
"Could not parse read-only command arguments: {error}"View on GitHub (pinned to 73e0f67d83)