{"record":{"id":"5631e9c116ce3f45","repo":"gitbutlerapp/gitbutler","slug":"bitbucket-request-failed-status","errorCode":null,"errorMessage":"Bitbucket request failed: {status}","messagePattern":"Bitbucket request failed: (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-bitbucket/src/client.rs","lineNumber":557,"sourceCode":"                return Err(self\n                    .classify_repository_access_error(repository_status, workspace, repo_slug)\n                    .await);\n            }\n            return Err(anyhow::Error::new(HttpStatusError {\n                status: repository_status,\n            })\n            .context(\"Failed to verify Bitbucket repository access\"));\n        }\n        if matches!(\n            status,\n            reqwest::StatusCode::UNAUTHORIZED | reqwest::StatusCode::FORBIDDEN\n        ) {\n            return Err(self\n                .classify_repository_access_error(status, workspace, repo_slug)\n                .await);\n        }\n        if !status.is_success() {\n            bail!(\"Bitbucket request failed: {status}\");\n        }\n\n        let page: Paginated<BitbucketApiBuildStatus> = response.json().await?;\n        let mut statuses = page.values;\n        if let Some(next) = page.next {\n            statuses.extend(self.get_paginated(next).await?);\n        }\n        Ok(Some(\n            statuses\n                .into_iter()\n                .map(BitbucketBuildStatus::from_api)\n                .collect(),\n        ))\n    }\n\n    async fn repository_status(\n        &self,\n        workspace: &str,","sourceCodeStart":539,"sourceCodeEnd":575,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-bitbucket/src/client.rs#L539-L575","documentation":"Raised while fetching build statuses for a commit after two earlier guards already ran: repository access was verified (failure returns early with a 'Failed to verify Bitbucket repository access' context) and 401/403 were reclassified by classify_repository_access_error(). This bail therefore catches every other non-success status from the build-status endpoint.","triggerScenarios":"Calling the build-status lookup and receiving something other than 2xx/401/403: typically 404 (no build statuses or unknown commit key), 429 rate limiting, or a 5xx from Bitbucket's pipeline-status API.","commonSituations":"Polling build status in a loop right after pushing (status key not yet registered); aggressive CI polling tripping rate limits; Bitbucket Cloud incidents.","solutions":["Treat 429/5xx as transient: back off and retry the status lookup","For 404, confirm the commit sha/key used for the status query actually exists in that repo","If it persists, capture the status code and check Bitbucket status page / API changelog","Rate-limit your own polling loop (e.g. exponential backoff between checks)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"null // nothing to validate client-side beyond what the client already verifies; throttle instead\nstatic POLL: Lazy<RateLimiter> = Lazy::new(|| RateLimiter::per_minute(30));\nPOLL.wait().await;","typeGuard":null,"tryCatchPattern":"// transient-oriented retry, since 401/403 are already classified elsewhere\nfor attempt in 0..4 {\n    match client.build_statuses(ws, slug, sha).await {\n        Err(e) if embedded_status(&e).is_some_and(|s| s.as_u16() == 429 || s.is_server_error())\n            => { tokio::time::sleep(backoff(attempt)).await; }\n        r => return r.map_err(Into::into),\n    }\n}","preventionTips":["Poll build status with exponential backoff, not fixed intervals","Treat a 404 shortly after a push as 'status not registered yet' and retry once","Cache the last seen status per commit to avoid refetching"],"tags":["bitbucket","build-status","http","polling"],"backgroundTag":"http-error-response","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}