{"record":{"id":"c06e040c8d210143","repo":"gitbutlerapp/gitbutler","slug":"bitbucket-repository-workspace-repo-slug-is","errorCode":null,"errorMessage":"Bitbucket repository '{workspace}/{repo_slug}' is inaccessible to this token, or the token is missing required scope `read:repository:bitbucket`","messagePattern":"Bitbucket repository '(.+?)/(.+?)' is inaccessible to this token, or the token is missing required scope `read:repository:bitbucket`","errorType":"http","errorClass":"HttpStatusError","httpStatus":null,"severity":"error","filePath":"crates/but-bitbucket/src/client.rs","lineNumber":641,"sourceCode":"        workspace: &str,\n        repo_slug: &str,\n    ) -> anyhow::Error {\n        if let Err(err) = self.get_authenticated().await {\n            if let Some(http_err) = err.downcast_ref::<HttpStatusError>() {\n                return match http_err.status {\n                    reqwest::StatusCode::UNAUTHORIZED => {\n                        err.context(\"Bitbucket credentials are invalid or expired\")\n                    }\n                    reqwest::StatusCode::FORBIDDEN => err.context(\n                        \"Bitbucket API token is missing required scope `read:user:bitbucket`\",\n                    ),\n                    _ => err.context(\"Failed to verify Bitbucket credentials\"),\n                };\n            }\n            return err.context(\"Failed to verify Bitbucket credentials\");\n        }\n\n        anyhow::Error::new(HttpStatusError { status }).context(format!(\n            \"Bitbucket repository '{workspace}/{repo_slug}' is inaccessible to this token, or the token is missing required scope `read:repository:bitbucket`\"\n        ))\n    }\n}\n\n/// Marks credential lookups that came up empty, so consumers can tell \"the\n/// user is not authenticated\" apart from a failing forge and e.g. keep\n/// serving cached data instead of surfacing an error.\npub(crate) const NOT_AUTHENTICATED: but_error::Context = but_error::Context::new_static(\n    but_error::Code::ForgeNotAuthenticated,\n    \"Not authenticated with Bitbucket. Connect your account under Settings → Integrations.\",\n);\n\npub(crate) fn resolve_account(\n    preferred_account: Option<&crate::BitbucketAccountIdentifier>,\n    storage: &but_forge_storage::Controller,\n) -> Result<crate::BitbucketAccountIdentifier, anyhow::Error> {\n    let known_accounts = crate::token::list_known_bitbucket_accounts(storage)?;","sourceCodeStart":623,"sourceCodeEnd":659,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-bitbucket/src/client.rs#L623-L659","documentation":"Raised by `classify_repository_access_error` when Bitbucket rejects repository access with an access-related status. It tells you the token authenticates but cannot read the repository — either the repo is private/inaccessible to that token's user, or the token lacks the `read:repository:bitbucket` scope.","triggerScenarios":"Calling `list_checks_for_ref` (or any code path that first verifies repo access) with a token whose user is not a member of the workspace, whose permission on the repo is below read, or whose scopes do not include `read:repository:bitbucket`; also for 404s where Bitbucket hides private repos to look nonexistent.","commonSituations":"Creating an API token / app password without ticking the Repository: Read scope; rotating to a new token with fewer scopes; the repository was moved to another workspace or made private; using a personal token of a user removed from the workspace.","solutions":["Regenerate the Bitbucket token and ensure the `read:repository:bitbucket` scope is granted.","Verify the token's user has at least Read permission on `{workspace}/{repo_slug}` in Bitbucket settings.","Confirm the workspace and repo slug in the target configuration are correct and the repo still exists there.","Re-authenticate (e.g. re-run `but login`) so the stored credentials match the intended account."],"exampleFix":"// before (app password scopes)\nscopes = [\"write:pullrequest:bitbucket\"]\n// after\nscopes = [\"write:pullrequest:bitbucket\", \"read:repository:bitbucket\"]","handlingStrategy":"validation","validationCode":"// before connecting, probe access with a cheap read\nlet me = reqwest::get(\"https://api.bitbucket.org/2.0/user\").bearer_auth(token).send().await?;\nlet repo = reqwest::get(format!(\"https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}\")).bearer_auth(token).send().await?;\nif !repo.status().is_success() { return Err(\"token cannot read this repo; check scope read:repository:bitbucket\".into()); }","typeGuard":null,"tryCatchPattern":"match client.list_checks_for_ref(&r).await {\n    Err(e) if e.to_string().contains(\"inaccessible to this token\") => {\n        eprintln!(\"Re-create your Bitbucket token with scope read:repository:bitbucket\");\n        prompt_relogin();\n    }\n    other => other?,\n}","preventionTips":["Always create Bitbucket tokens with `read:repository:bitbucket` plus the write scopes you need.","Confirm the token's user still has repo access after team/workspace changes.","Re-authenticate after rotating tokens or changing app-password scopes."],"tags":["bitbucket","permissions","token","scope"],"backgroundTag":"insufficient-permissions","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"}