{"record":{"id":"0684e0f6b18968b4","repo":"gitbutlerapp/gitbutler","slug":"github-graphql-pull-request-owner-repo-pr-number-not-found","errorCode":null,"errorMessage":"GitHub GraphQL pull request {owner}/{repo}#{pr_number} not found","messagePattern":"GitHub GraphQL pull request (.+?)/(.+?)#(.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-github/src/client.rs","lineNumber":520,"sourceCode":"        struct Repository {\n            pull_request: Option<GraphQlPullRequest>,\n        }\n\n        let data: Data = self\n            .graphql_query(\n                GQL_GET_PR,\n                &Variables {\n                    owner,\n                    repo,\n                    number: pr_number,\n                },\n            )\n            .await?;\n        let Some(pr) = data\n            .repository\n            .and_then(|repository| repository.pull_request)\n        else {\n            bail!(\"GitHub GraphQL pull request {owner}/{repo}#{pr_number} not found\");\n        };\n        Ok(pr.into())\n    }\n\n    /// List the top-level conversation (issue) comments on a pull request,\n    /// oldest first. Paginated; review-thread (diff) comments are not included.\n    pub async fn list_pull_request_comments(\n        &self,\n        owner: &str,\n        repo: &str,\n        pr_number: i64,\n    ) -> Result<Vec<PullRequestComment>> {\n        let url = format!(\n            \"{}/repos/{}/{}/issues/{}/comments\",\n            self.base_url, owner, repo, pr_number\n        );\n\n        Ok(self","sourceCodeStart":502,"sourceCodeEnd":538,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-github/src/client.rs#L502-L538","documentation":"The GraphQL get_pull_request query returns data.repository.pull_request as null when the repository or PR cannot be resolved (GitHub GraphQL returns errors with null data fields instead of HTTP errors). The client bails with this message to signal the PR was not found.","triggerScenarios":"Calling get_pull_request for a PR number that doesn't exist, in a repo the token can't see, or on a renamed/deleted repository — GraphQL resolves repository/pull_request to null.","commonSituations":"PR number from another repo or org; private repo with a token lacking access (GraphQL silently nulls); PR deleted between listing and fetch; typo in owner/repo node names.","solutions":["Verify the PR exists via REST: GET /repos/{owner}/{repo}/pulls/{n}","Check the token can read the repo (GraphQL returns null instead of 404 for unauthorized repos)","Confirm owner/repo strings match the GraphQL node names exactly (case-sensitive owner, repo slug)"],"exampleFix":"// before\nlet pr = client.get_pull_request(\"acme\", \"Repo\", 12).await?; // wrong slug case\n// after\nlet pr = client.get_pull_request(\"acme\", \"repo\", 12).await?;","handlingStrategy":"try-catch","validationCode":"let resp = reqwest::Client::new()\n    .get(&format!(\"https://api.github.com/repos/{owner}/{repo}/pulls/{n}\"))\n    .header(\"Authorization\", format!(\"Bearer {token}\"))\n    .send().await?;\nif resp.status() == reqwest::StatusCode::NOT_FOUND {\n    return Err(\"PR does not exist or is inaccessible\".into());\n}","typeGuard":null,"tryCatchPattern":"match client.get_pull_request(owner, repo, n).await {\n    Ok(pr) => pr,\n    Err(e) if e.to_string().contains(\"not found\") => {\n        eprintln!(\"PR #{n} unavailable; skipping\");\n        return Ok(None);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Remember GraphQL returns null (not 404) for inaccessible PRs","Verify repo visibility vs token scopes when PRs 'vanish'","Check owner/repo node names exactly match GitHub slugs"],"tags":["github","graphql","pull-request","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}