{"record":{"id":"6c51c9d1e58b0fb2","repo":"Hmbown/CodeWhale","slug":"shell-command-failed-status","errorCode":null,"errorMessage":"shell command failed (status={}): {}","messagePattern":"shell command failed \\(status=(.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/shell_dispatcher.rs","lineNumber":410,"sourceCode":"                if self.restore {\n                    let _ = crossterm::terminal::enable_raw_mode();\n                }\n            }\n        }\n        let _guard = FgRawModeGuard {\n            restore: raw_mode_was_enabled,\n        };\n\n        let mut cmd = self.build_command(shell_command);\n        cmd.current_dir(cwd);\n\n        let output = cmd\n            .output()\n            .with_context(|| format!(\"failed to execute shell command: {shell_command}\"))?;\n\n        if !output.status.success() {\n            let stderr = String::from_utf8_lossy(&output.stderr);\n            anyhow::bail!(\n                \"shell command failed (status={}): {}\",\n                output.status,\n                stderr.trim()\n            );\n        }\n\n        let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();\n        Ok(stdout)\n    }\n\n    // -- Detection --------------------------------------------------------\n\n    fn detect_shell() -> ShellKind {\n        #[cfg(test)]\n        {\n            // Non-blocking on purpose. This runs inside the `LazyLock`\n            // initializer in `global_dispatcher()`, and a test that holds the\n            // env barrier can reach `global_dispatcher()` while another thread","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/shell_dispatcher.rs#L392-L428","documentation":"Thrown by ShellDispatcher when a dispatched shell command runs to completion but exits non-zero (crates/tui/src/shell_dispatcher.rs). The captured stderr, trimmed, is appended after the status code. Spawn failures are a different error ('failed to execute shell command'), so this one strictly means the process started, ran, and failed by its own exit code.","triggerScenarios":"Running a bang command or shell tool whose process exits non-zero: failing builds ('!cargo build'), failing tests, grep with no matches (exit 1), 'git diff --exit-code' with changes. The dispatcher runs the command in the session cwd, so path-dependent commands that fail there land here.","commonSituations":"Build or test pipelines invoked from the TUI where the underlying tool already printed the real cause to stderr; commands that use exit codes as signals (grep -q, diff --exit-code); commands assuming a different working directory than the session cwd.","solutions":["Read the stderr in the message; it is the underlying tool's own output and names the root cause.","Re-run the command directly in a terminal from the same cwd to see full, untrimmed output.","If the non-zero exit is expected (grep no-match, diff), make the command exit 0 itself: append '|| true' or restructure.","If the shell selection is wrong (command exists in another shell), fix shell detection; spawn failure is the sibling error to compare against."],"exampleFix":"# before\n!grep -q TODO src/main.rs\n# exits 1 when no match -> error surfaced\n\n# after\n!grep -q TODO src/main.rs || true","handlingStrategy":"try-catch","validationCode":"// Preflight: confirm the binary resolves in the dispatcher's shell and cwd\nlet check = Command::new(\"sh\")\n    .arg(\"-c\")\n    .arg(format!(\"command -v -- {binary:?} >/dev/null 2>&1\"))\n    .current_dir(cwd)\n    .status()?;\nif !check.success() {\n    eprintln!(\"{binary} not found on PATH for this shell/cwd\");\n}","typeGuard":null,"tryCatchPattern":"match dispatcher.run(&cmd, cwd).await {\n    Err(err) if err.to_string().starts_with(\"shell command failed (status=\") => {\n        // the command ran and exited non-zero; stderr is embedded in the message\n        let root = err.to_string(); // surface it, do not retry blindly\n    }\n    Err(err) => { /* spawn/execution failure: check PATH and shell selection */ }\n    Ok(stdout) => { /* use stdout */ }\n}","preventionTips":["Expect non-zero exits from signal-style commands (grep -q, diff --exit-code) and neutralize with '|| true' where the exit code is not an error.","Run builds and tests from the same cwd the session uses so relative paths resolve identically.","Read the embedded stderr before assuming the dispatcher itself misbehaved."],"tags":["shell","process","exit-status","tui","rust"],"backgroundTag":"shell-command-non-zero-exit","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}