{"record":{"id":"bbf30b5914bd2aaf","repo":"gitbutlerapp/gitbutler","slug":"bitbucket-request-failed","errorCode":null,"errorMessage":"Bitbucket request failed: {}","messagePattern":"Bitbucket request failed: (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-bitbucket/src/client.rs","lineNumber":106,"sourceCode":"    }\n\n    /// Fetch every `values` entry across a paginated Bitbucket collection,\n    /// following the `next` cursor URL until exhausted. Errors out if the\n    /// `MAX_PAGES` safety cap is hit rather than silently truncating the result.\n    async fn get_paginated<T: DeserializeOwned>(&self, initial_url: String) -> Result<Vec<T>> {\n        let mut items = Vec::new();\n        let mut next = Some(initial_url);\n        let mut pages = 0;\n\n        while let Some(url) = next.take() {\n            if pages >= MAX_PAGES {\n                bail!(\"Bitbucket pagination exceeded the {MAX_PAGES}-page safety cap\");\n            }\n            pages += 1;\n\n            let response = self.client.get(&url).send().await?;\n            if !response.status().is_success() {\n                bail!(\"Bitbucket request failed: {}\", response.status());\n            }\n            let page: Paginated<T> = response.json().await?;\n            items.extend(page.values);\n            next = page.next;\n        }\n\n        Ok(items)\n    }\n\n    /// Fetch a single page of a Bitbucket collection without following the\n    /// `next` cursor. Used for \"most recent\" listings where the caller sorts\n    /// server-side and only needs the head of the result set.\n    async fn get_first_page<T: DeserializeOwned>(&self, url: String) -> Result<Vec<T>> {\n        let response = self.client.get(&url).send().await?;\n        if !response.status().is_success() {\n            bail!(\"Bitbucket request failed: {}\", response.status());\n        }\n        let page: Paginated<T> = response.json().await?;","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-bitbucket/src/client.rs#L88-L124","documentation":"Raised inside get_paginated() when any page of a Bitbucket Cloud API request returns a non-2xx HTTP status; the message embeds the reqwest StatusCode. Because it fires mid-pagination, earlier pages may already have been collected but are discarded when this error propagates.","triggerScenarios":"Calling a paginated Bitbucket listing (open PRs, build statuses, ...) that gets a 401 (expired/revoked token), 403 (missing scope), 404 (wrong workspace/repo slug), 429 (rate limit), or 5xx from api.bitbucket.org while following the 'next' cursor.","commonSituations":"Long-lived CLI/desktop sessions whose OAuth token expired between pages; tokens created without read:pullrequest scope; typos in repo slug; Bitbucket Cloud incidents or rate limiting during bulk listing.","solutions":["Classify on the embedded status: 401/403 -> re-run 'but config forge auth' and retry; 404 -> verify workspace and repo slug spelling; 429/5xx -> retry with exponential backoff","Check network/proxy reachability of api.bitbucket.org","If the failure happens after page 1, suspect a token revoked mid-walk or rate limiting and restart the full listing after recovery"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"null // no cheap pre-check for arbitrary server statuses; validate auth instead\nlet accounts = but_bitbucket::token::list_known_bitbucket_accounts(storage)?;\nanyhow::ensure!(!accounts.is_empty(), \"authenticate first via 'but config forge auth'\");","typeGuard":null,"tryCatchPattern":"// classify the embedded status, retry only transient classes\nfor attempt in 0..5 {\n    match client.list_open_prs(ws, slug).await {\n        Err(e) if status_of(&e).is_some_and(|s| s.as_u16() == 429 || s.is_server_error()) => {\n            tokio::time::sleep(backoff(attempt)).await; continue;\n        }\n        r => break r,\n    }\n}?","preventionTips":["Refresh tokens proactively before long batch walks","Verify workspace/repo slug at integration setup to avoid mid-walk 404s","Wrap paginated calls with retry-on-429/5xx and give up fast on 4xx"],"tags":["bitbucket","http","api","status-code"],"backgroundTag":"http-error-response","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}