{"record":{"id":"a0244ae7061b2799","repo":"gitbutlerapp/gitbutler","slug":"command-not-found","errorCode":null,"errorMessage":"command not found","messagePattern":"command not found","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"crates/but/src/command/legacy/status/tui/app/command_mode.rs","lineNumber":221,"sourceCode":"                        return Ok(());\n                    }\n                };\n                let Some(binary) = args.next() else {\n                    return Ok(());\n                };\n                let mut cmd = Command::new(binary);\n                cmd.args(args);\n                cmd\n            }\n        };\n\n        cmd.current_dir(ctx.workdir_or_fail()?);\n\n        let mut child = match cmd.spawn() {\n            Ok(child) => child,\n            Err(err) => {\n                if err.kind() == std::io::ErrorKind::NotFound {\n                    self.push_transient_error(anyhow!(\"command not found\"));\n                    return Ok(());\n                } else {\n                    return Err(err).context(\"failed to start command\");\n                }\n            }\n        };\n        let status = child.wait()?;\n\n        if !IN_TEST {\n            out.prompt_single_line(\"\\npress enter to continue...\")?;\n        }\n\n        if status.success() {\n            messages.extend([\n                Message::EnterNormalModeAfterConfirmingOperation,\n                Message::Reload(None, ReloadCause::Mutation),\n            ]);\n        } else {","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/legacy/status/tui/app/command_mode.rs#L203-L239","documentation":"Shown in the `but` TUI command mode: input typed after `:` (but command) or `!` (shell command) is shell-split with `shell_words::split` and the first token is spawned with `Command::new(binary)`. When the OS reports `ErrorKind::NotFound` — the binary is not on PATH or the path is wrong — the TUI pushes a transient 'command not found' message and keeps running; other spawn errors propagate with 'failed to start command'.","triggerScenarios":"Typing a shell command (`!...`) whose binary is not installed or not on the TUI process's PATH, e.g. `!gitx` with gitx missing, or `!./tool` from the wrong directory.","commonSituations":"Launching the TUI from a GUI launcher or minimal-PATH environment where usual shell PATH entries are absent; typo in the command name; tool simply not installed; relative path not resolved because cwd differs from expectation.","solutions":["Check the spelling of the command","Verify the binary is reachable in that environment: run `!which <cmd>` from the TUI or echo $PATH from a shell that matches the launch environment","Use an absolute path for the command (e.g. `!/usr/bin/git status`) to take PATH out of the equation","Launch `but` from your normal shell (with full PATH) rather than from a GUI/app launcher"],"exampleFix":"# before: not on the TUI's PATH\n!gitui\n\n# after: absolute path, or fix PATH\n!/opt/homebrew/bin/gitui","handlingStrategy":"validation","validationCode":"let binary = args[0].as_ref();\nif !binary.to_string_lossy().contains(std::path::MAIN_SEPARATOR_str())\n    && which::which(binary).is_err()\n{\n    self.push_transient_error(anyhow!(\"command not found: {binary:?} (check PATH)\"));\n    return Ok(());\n}","typeGuard":"fn is_not_found(err: &std::io::Error) -> bool {\n    err.kind() == std::io::ErrorKind::NotFound\n}","tryCatchPattern":"match cmd.spawn() {\n    Ok(child) => { let _ = child.wait()?; }\n    Err(err) if is_not_found(&err) => {\n        self.push_transient_error(anyhow!(\"command not found\"));\n        return Ok(());\n    }\n    Err(err) => return Err(err).context(\"failed to start command\"),\n}","preventionTips":["Type absolute paths for commands not guaranteed to be on PATH (`!/usr/bin/git ...`)","Launch the TUI from a normal login shell so PATH is fully populated","Verify availability from inside the TUI with `!which <cmd>` before relying on it","Check spelling first — shell_words splitting means typos surface as NotFound"],"tags":["rust","cli","tui","process-spawn","path","shell"],"backgroundTag":"command-not-found","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}