Hmbown/CodeWhale · error

gh did not report a pull request URL; refusing to invent…

Error message

gh did not report a pull request URL; refusing to invent one.

What it means

`open_pr_github` shells out to `gh pr create` and trusts only its stdout for the new pull request URL. If the command succeeds but stdout does not start with `https://`, the function refuses to return a fabricated URL and bails instead. This guards callers against silent `gh` behavior changes, wrappers, or partial output.

Solutions

  1. Run `gh pr create` manually in the same repo and inspect its raw stdout to see what it actually prints.
  2. Update the GitHub CLI (`gh --version`, then upgrade) to a version whose `pr create` prints the PR URL on stdout.
  3. Remove any shell alias/function or wrapper intercepting `gh` inside the dispatch environment.
  4. Check `gh auth status` and target-repo flags; an interactive prompt or degraded output can mean the PR was not actually created.
  5. If `gh` emitted a warning-only stdout, re-run after clearing `GH_*` env vars that alter output formatting.

Example fix

// before: rely on gh default output
let url = String::from_utf8_lossy(&output.stdout).trim().to_string();
// after: normalize, e.g. take the last https URL token found
let stdout = String::from_utf8_lossy(&output.stdout);
let url = stdout.split_whitespace().rev().find(|t| t.starts_with("https://")).unwrap_or("").to_string();
Defensive patterns

Strategy: validation

Validate before calling

// check gh output before trusting dispatch
let out = std::process::Command::new("gh").args(["pr", "view", "--json", "url"]).output()?;
if !String::from_utf8_lossy(&out.stdout).contains("https://") {
    eprintln!("gh not producing URLs; update gh or check auth before dispatch");
}

Prevention

When it happens

Trigger: Calling `open` (PR dispatch) with the GitHub provider when `gh pr create` exits 0 but prints no URL or prints non-URL text (warnings, notices, empty stdout) on stdout.

Common situations: Outdated or customized `gh` versions that changed output format; `gh` wrapped by a shell function/alias that swallows stdout; enterprise proxy or GHES emitting extra text before the URL; stdout redirected or captured by a wrapper that drops the final line.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

    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://") {
        bail!("gh did not report a pull request URL; refusing to invent one.");
    }
    Ok(url)
}

fn open_pr_gitee(
    slug: &str,
    job: &CloudJob,
    patch: &PatchReceipt,
    title: &str,
    body: &str,
) -> Result<String> {
    let token = read_service_token("gitee").ok_or_else(|| {
        anyhow!("a Gitee access token is not configured in the Codewhale service slot; the branch was pushed but no pull request was opened")
    })?;
    let url = validate_outbound_origin(&gitee_pr_url(slug))?;
    let response = crate::tls::reqwest_blocking_client_builder()
        .connect_timeout(std::time::Duration::from_secs(8))
        .timeout(std::time::Duration::from_secs(30))

View on GitHub (pinned to 73e0f67d83)