Hmbown/CodeWhale · error · anyhow::Error

the GitHub pull request needs the gh CLI on PATH

Error message

the GitHub pull request needs the gh CLI on PATH

What it means

open_pr_github shells out to the external `gh` CLI to create the pull request; if crate::dependencies::Gh::command() returns None (gh not found on PATH) the PR step fails with this error, after the branch has already been pushed.

Solutions

  1. Install the GitHub CLI (gh) and ensure it is on PATH, then run `gh auth login`.
  2. Fix the PATH of the environment that launches Codewhale so the gh binary is discoverable.
  3. As a fallback, create the PR manually from the pushed branch in the GitHub UI.

Example fix

# before
$ which gh   # not found
# after
$ brew install gh && gh auth status
Defensive patterns

Strategy: try-catch

Validate before calling

if crate::dependencies::Gh::command().is_none() {
    eprintln!("gh CLI is required for GitHub PRs; install it first");
}

Try / catch

match open_pr_github(slug, job, patch, title, body) {
    Err(e) if e.to_string().contains("needs the gh CLI on PATH") => {
        // skip PR step; branch already pushed, print manual PR URL
    }
    other => other?,
}

Prevention

When it happens

Trigger: open -> open_pr_github on a GitHub forge job while the gh binary is not installed or not on the PATH of the process running Codewhale.

Common situations: Running Codewhale in a container/systemd/CI environment where gh is not installed; a minimal shell PATH missing /usr/local/bin; gh installed only via an interactive-user version manager.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/0a4684581471c00c. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/dispatch_runner.rs:594

            args.first().unwrap_or(&""),
            sanitize_error(&String::from_utf8_lossy(&output.stderr))
        );
    }
    Ok(String::from_utf8_lossy(&output.stdout).to_string())
}

fn open_pr_github(
    slug: &str,
    job: &CloudJob,
    patch: &PatchReceipt,
    title: &str,
    body: &str,
) -> Result<String> {
    let body_dir = tempfile::tempdir().context("could not stage the PR body")?;
    let body_file = body_dir.path().join("body.md");
    std::fs::write(&body_file, body).context("could not write the PR body")?;
    let mut command = crate::dependencies::Gh::command()
        .ok_or_else(|| anyhow!("the GitHub pull request needs the gh CLI on PATH"))?;
    command.args(gh_pr_create_argv(
        slug,
        &patch.base_branch,
        &job.branch,
        title,
        &body_file.to_string_lossy(),
    ));
    let output = command
        .output()
        .context("failed to start gh for the pull request")?;
    if !output.status.success() {
        bail!(
            "gh pr create failed: {}",
            sanitize_error(&String::from_utf8_lossy(&output.stderr))
        );
    }
    let url = String::from_utf8_lossy(&output.stdout).trim().to_string();
    if !url.starts_with("https://") {

View on GitHub (pinned to 73e0f67d83)