Hmbown/CodeWhale · error · anyhow::Error

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

Error message

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

What it means

After creating the pull request via the Gitee API, open_pr_gitee extracts html_url from the JSON response and only accepts a trimmed https:// URL; if the response lacks a usable html_url the PR URL is not returned — the code refuses to invent or guess one.

Solutions

  1. Log/inspect the raw Gitee response body to see what was actually returned, and fix token/permissions if it is an auth error payload.
  2. Retry the request — a transient gateway/CDN response can omit fields.
  3. If the PR was created (check the Gitee UI), record its URL manually; otherwise fix the Gitee instance/API version and re-run.

Example fix

// before
{"id": 123}  // no html_url -> error
// after
{"id": 123, "html_url": "https://gitee.com/acme/widget/pulls/7"}
Defensive patterns

Strategy: try-catch

Validate before calling

// cannot pre-check the response; guard after parsing:
let html_url = body.get("html_url").and_then(serde_json::Value::as_str).unwrap_or_default();
if !html_url.starts_with("https://") { eprintln!("Gitee response missing html_url: {body}"); }

Try / catch

match open_pr_gitee(slug, job, patch, title, body) {
    Err(e) if e.to_string().contains("refusing to invent") => {
        // log raw response; check Gitee UI for the PR before retrying
    }
    other => other?,
}

Prevention

When it happens

Trigger: The Gitee create-PR API returns JSON without a usable html_url string field (or with a non-https value) when open_pr_gitee parses the response body.

Common situations: Gitee API changes or a proxy/gateway returning a wrapped or partial payload; the token lacks permission so an error body without html_url comes back; a self-hosted Gitee instance serving plain-http URLs.

Related errors


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

Appendix: source

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

            ("base", patch.base_branch.as_str()),
            ("body", body),
        ])
        .send()
        .context("could not reach Gitee")?;
    let status = response.status();
    let text = response.text().unwrap_or_default();
    if !status.is_success() {
        bail!("Gitee pull request create failed (HTTP {status}).");
    }
    let parsed: serde_json::Value =
        serde_json::from_str(&text).context("Gitee returned invalid JSON")?;
    parsed
        .get("html_url")
        .and_then(serde_json::Value::as_str)
        .map(str::trim)
        .filter(|url| url.starts_with("https://"))
        .map(|url| url.to_string())
        .ok_or_else(|| anyhow!("Gitee did not report a pull request URL; refusing to invent one."))
}

fn open_pr_cnb(
    slug: &str,
    job: &CloudJob,
    patch: &PatchReceipt,
    title: &str,
    body: &str,
) -> Result<String> {
    let token = read_service_token("cnb").ok_or_else(|| {
        anyhow!("a CNB 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(&cnb_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))
        .redirect(reqwest::redirect::Policy::none())
        .build()

View on GitHub (pinned to 73e0f67d83)