{"record":{"id":"d005e87e15d5bdab","repo":"Hmbown/CodeWhale","slug":"gh-did-not-report-a-pull-request-url-refusing-to-invent-one","errorCode":null,"errorMessage":"gh did not report a pull request URL; refusing to invent one.","messagePattern":"gh did not report a pull request URL; refusing to invent one\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/dispatch_runner.rs","lineNumber":613,"sourceCode":"    command.args(gh_pr_create_argv(\n        slug,\n        &patch.base_branch,\n        &job.branch,\n        title,\n        &body_file.to_string_lossy(),\n    ));\n    let output = command\n        .output()\n        .context(\"failed to start gh for the pull request\")?;\n    if !output.status.success() {\n        bail!(\n            \"gh pr create failed: {}\",\n            sanitize_error(&String::from_utf8_lossy(&output.stderr))\n        );\n    }\n    let url = String::from_utf8_lossy(&output.stdout).trim().to_string();\n    if !url.starts_with(\"https://\") {\n        bail!(\"gh did not report a pull request URL; refusing to invent one.\");\n    }\n    Ok(url)\n}\n\nfn open_pr_gitee(\n    slug: &str,\n    job: &CloudJob,\n    patch: &PatchReceipt,\n    title: &str,\n    body: &str,\n) -> Result<String> {\n    let token = read_service_token(\"gitee\").ok_or_else(|| {\n        anyhow!(\"a Gitee access token is not configured in the Codewhale service slot; the branch was pushed but no pull request was opened\")\n    })?;\n    let url = validate_outbound_origin(&gitee_pr_url(slug))?;\n    let response = crate::tls::reqwest_blocking_client_builder()\n        .connect_timeout(std::time::Duration::from_secs(8))\n        .timeout(std::time::Duration::from_secs(30))","sourceCodeStart":595,"sourceCodeEnd":631,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/dispatch_runner.rs#L595-L631","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run `gh pr create` manually in the same repo and inspect its raw stdout to see what it actually prints.","Update the GitHub CLI (`gh --version`, then upgrade) to a version whose `pr create` prints the PR URL on stdout.","Remove any shell alias/function or wrapper intercepting `gh` inside the dispatch environment.","Check `gh auth status` and target-repo flags; an interactive prompt or degraded output can mean the PR was not actually created.","If `gh` emitted a warning-only stdout, re-run after clearing `GH_*` env vars that alter output formatting."],"exampleFix":"// before: rely on gh default output\nlet url = String::from_utf8_lossy(&output.stdout).trim().to_string();\n// after: normalize, e.g. take the last https URL token found\nlet stdout = String::from_utf8_lossy(&output.stdout);\nlet url = stdout.split_whitespace().rev().find(|t| t.starts_with(\"https://\")).unwrap_or(\"\").to_string();","handlingStrategy":"validation","validationCode":"// check gh output before trusting dispatch\nlet out = std::process::Command::new(\"gh\").args([\"pr\", \"view\", \"--json\", \"url\"]).output()?;\nif !String::from_utf8_lossy(&out.stdout).contains(\"https://\") {\n    eprintln!(\"gh not producing URLs; update gh or check auth before dispatch\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep `gh` updated and unaliased in automation environments.","Verify `gh auth status` and run `gh pr create` once manually after tooling changes.","Pin the gh version used by automation to a known-good release."],"tags":["github","cli","pull-request","subprocess"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}