{"record":{"id":"65d9f1a748ccf743","repo":"gitbutlerapp/gitbutler","slug":"pr-number-must-be-greater-than-0","errorCode":null,"errorMessage":"PR number must be greater than 0","messagePattern":"PR number must be greater than 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-github/src/client.rs","lineNumber":1504,"sourceCode":"                .and_then(|value| {\n                    value\n                        .get(\"message\")\n                        .and_then(|m| m.as_str().map(String::from))\n                })\n                .unwrap_or(body);\n            bail!(\"GitHub refused the merge ({status}): {reason}\");\n        }\n\n        Ok(())\n    }\n\n    /// Set the draftiness of a PR.\n    pub async fn set_pull_request_draft_state(\n        &self,\n        params: &SetPullRequestDraftStateParams<'_>,\n    ) -> Result<()> {\n        if params.pr_number <= 0 {\n            bail!(\"PR number must be greater than 0\");\n        }\n\n        let pull_request_id = self\n            .get_pull_request_node_id(params.owner, params.repo, params.pr_number)\n            .await?;\n\n        if params.draft {\n            self.set_pull_request_to_draft(&pull_request_id).await\n        } else {\n            self.set_pull_request_to_ready_for_review(&pull_request_id)\n                .await\n        }\n    }\n\n    async fn set_pull_request_to_ready_for_review(\n        &self,\n        pull_request_id: &PullRequestNodeId,\n    ) -> Result<()> {","sourceCodeStart":1486,"sourceCodeEnd":1522,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-github/src/client.rs#L1486-L1522","documentation":"Parameter validation in set_pull_request_draft_state: the caller passed a pr_number of zero or below. GitHub PR numbers are positive integers, so the request is rejected client-side before any network call is made.","triggerScenarios":"Calling set_pull_request_draft_state with SetPullRequestDraftStateParams whose pr_number is 0, negative, or an uninitialized/default value (e.g. an unwrap_or(0) upstream).","commonSituations":"Parsing a PR number from a string or URL that failed and defaulted to 0; a caller passing Option::unwrap_or_default; off-by-one when deriving the number from a branch index.","solutions":["Fix the caller to pass the real PR number (> 0)","Validate/persist the pr_number where it is produced instead of defaulting to 0","Parse PR numbers from strings with proper error propagation (e.g. str::parse::<u64>() with ?) rather than unwrap_or(0)"],"exampleFix":"// before\nlet pr_number = url.rsplit('/').next().and_then(|s| s.parse().ok()).unwrap_or(0);\n// after\nlet pr_number: u64 = url.rsplit('/').next().unwrap().parse()?;","handlingStrategy":"validation","validationCode":"fn validate_pr_number(pr_number: i64) -> anyhow::Result<u64> {\n    u64::try_from(pr_number).ok().filter(|n| *n > 0).context(\"PR number must be greater than 0\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never default PR numbers with unwrap_or(0); propagate parse errors","Validate pr_number at the boundary where it is parsed from strings/URLs","Keep pr_number as a non-zero type (u64 with explicit checks) in your config structs"],"tags":["validation","argument","pull-request"],"backgroundTag":"value-out-of-range","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"}