gitbutlerapp/gitbutler · error · anyhow::Error
Bitbucket request failed: {status}
Error message
Bitbucket request failed: {status} What it means
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.
Source
Thrown at crates/but-bitbucket/src/client.rs:557
return Err(self
.classify_repository_access_error(repository_status, workspace, repo_slug)
.await);
}
return Err(anyhow::Error::new(HttpStatusError {
status: repository_status,
})
.context("Failed to verify Bitbucket repository access"));
}
if matches!(
status,
reqwest::StatusCode::UNAUTHORIZED | reqwest::StatusCode::FORBIDDEN
) {
return Err(self
.classify_repository_access_error(status, workspace, repo_slug)
.await);
}
if !status.is_success() {
bail!("Bitbucket request failed: {status}");
}
let page: Paginated<BitbucketApiBuildStatus> = response.json().await?;
let mut statuses = page.values;
if let Some(next) = page.next {
statuses.extend(self.get_paginated(next).await?);
}
Ok(Some(
statuses
.into_iter()
.map(BitbucketBuildStatus::from_api)
.collect(),
))
}
async fn repository_status(
&self,
workspace: &str,View on GitHub (pinned to caf1f223d3)
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)
Defensive patterns
Strategy: retry
Validate before calling
null // nothing to validate client-side beyond what the client already verifies; throttle instead static POLL: Lazy<RateLimiter> = Lazy::new(|| RateLimiter::per_minute(30)); POLL.wait().await;
Try / catch
// transient-oriented retry, since 401/403 are already classified elsewhere
for attempt in 0..4 {
match client.build_statuses(ws, slug, sha).await {
Err(e) if embedded_status(&e).is_some_and(|s| s.as_u16() == 429 || s.is_server_error())
=> { tokio::time::sleep(backoff(attempt)).await; }
r => return r.map_err(Into::into),
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Polling build status in a loop right after pushing (status key not yet registered); aggressive CI polling tripping rate limits; Bitbucket Cloud incidents.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Bitbucket request failed: {}
- Failed to update pull request: {status} - {error_text}
- Failed to merge pull request: {status} - {error_text}
- Failed to decline pull request: {status} - {error_text}
- Failed to fetch repository: {status} - {error_text}
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/5631e9c116ce3f45.
Report an issue: GitHub.