gitbutlerapp/gitbutler · error · HttpStatusError
Bitbucket repository '{workspace}/{repo_slug}' is inaccessib
Error message
Bitbucket repository '{workspace}/{repo_slug}' is inaccessible to this token, or the token is missing required scope `read:repository:bitbucket` What it means
Terminal message of classify_repository_access_error in but-bitbucket: the repository endpoint denied access and the /user probe could not narrow the cause (a successful /user proves the token itself is valid; a failed one gets its own context). The remaining explanations: this token cannot see {workspace}/{repo_slug}, or it lacks the read:repository:bitbucket scope required by GET /repositories/{ws}/{slug}. Bitbucket deliberately hides missing-scope from no-access, so both are listed.
Source
Thrown at crates/but-bitbucket/src/client.rs:614
workspace: &str,
repo_slug: &str,
) -> anyhow::Error {
if let Err(err) = self.get_authenticated().await {
if let Some(http_err) = err.downcast_ref::<HttpStatusError>() {
return match http_err.status {
reqwest::StatusCode::UNAUTHORIZED => {
err.context("Bitbucket credentials are invalid or expired")
}
reqwest::StatusCode::FORBIDDEN => err.context(
"Bitbucket API token is missing required scope `read:user:bitbucket`",
),
_ => err.context("Failed to verify Bitbucket credentials"),
};
}
return err.context("Failed to verify Bitbucket credentials");
}
anyhow::Error::new(HttpStatusError { status }).context(format!(
"Bitbucket repository '{workspace}/{repo_slug}' is inaccessible to this token, or the token is missing required scope `read:repository:bitbucket`"
))
}
}
pub(crate) fn resolve_account(
preferred_account: Option<&crate::BitbucketAccountIdentifier>,
storage: &but_forge_storage::Controller,
) -> Result<crate::BitbucketAccountIdentifier, anyhow::Error> {
let known_accounts = crate::token::list_known_bitbucket_accounts(storage)?;
let Some(default_account) = known_accounts.first() else {
bail!(
"No authenticated Bitbucket users found.\nRun 'but config forge auth' to authenticate with Bitbucket."
);
};
let account = if let Some(account) = preferred_account {
if known_accounts.contains(account) {
accountView on GitHub (pinned to 2497b8007a)
Solutions
- Grant read:repository:bitbucket to the token (plus read:user:bitbucket), then re-add it
- Confirm workspace and slug exactly as in the browser URL and retype them
- Check the token's account is a member of the workspace that owns the repository
- Test the raw endpoint: curl -s -o /dev/null -w '%{http_code}' -H 'Authorization: Bearer $TOKEN' https://api.bitbucket.org/2.0/repositories/<ws>/<slug>
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight right after token entry: the repository endpoint must answer 200
curl -s -o /dev/null -w '%{http_code}' \
-H 'Authorization: Bearer $TOKEN' \
https://api.bitbucket.org/2.0/repositories/<workspace>/<repo_slug>
// 200 = access OK; 401/403 = scope or auth problem; 404 = wrong slug or no access Type guard
fn is_repository_access_error(err: &anyhow::Error) -> bool {
err.chain().any(|c| c.to_string().contains("read:repository:bitbucket"))
} Try / catch
if let Err(err) = client.list_checks_for_ref(ws, slug, ref_).await {
if is_repository_access_error(&err) {
// stop the onboarding flow and ask for scope fix / correct slug
return Err(err.context("fix token scopes or workspace/slug, then retry"));
}
return Err(err);
} Prevention
- Validate repository access immediately when a token is entered, not at first PR/check use
- Keep a scope checklist per forge feature and assert it during setup
- Copy workspace/slug from the repository URL, never from memory
When it happens
Trigger: Fetching checks or PR data with a token that has no access to the repository (404 masquerading as denial); a token created without read:repository:bitbucket (403); workspace or repo_slug typo; private repository in a workspace the token's account does not belong to.
Common situations: Workspace-scoped API keys; repository renamed after its URL was copied; user has several workspaces and the token was issued under the wrong one.
Related errors
- Failed to create pull request: {status} - {error_text}
- Failed to verify Bitbucket repository access
- Failed to persist action: {e}
- Failed to list actions: {e}
- CliInstallCancelled
AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17).
Data as JSON: /api/errors/c06e040c8d210143.
Report an issue: GitHub.