{"record":{"id":"b8a69208c32ceb77","repo":"gitbutlerapp/gitbutler","slug":"not-authenticated","errorCode":"NOT_AUTHENTICATED","errorMessage":"No Bitbucket access token found for account '{account_id}'.\nRun 'but config forge auth' to re-authenticate.","messagePattern":"No Bitbucket access token found for account '(.+?)'\\.\nRun 'but config forge auth' to re-authenticate\\.","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-bitbucket/src/client.rs","lineNumber":64,"sourceCode":"            .default_headers(headers)\n            .timeout(BITBUCKET_REQUEST_TIMEOUT)\n            .build()?;\n\n        Ok(Self {\n            client,\n            base_url: BITBUCKET_API_BASE_URL.to_string(),\n        })\n    }\n\n    pub fn from_storage(\n        storage: &but_forge_storage::Controller,\n        preferred_account: Option<&crate::BitbucketAccountIdentifier>,\n    ) -> Result<Self> {\n        let account_id = resolve_account(preferred_account, storage)?;\n        if let Some(access_token) = crate::token::get_bb_access_token(&account_id, storage)? {\n            account_id.client(&access_token)\n        } else {\n            Err(anyhow::anyhow!(\n                \"No Bitbucket access token found for account '{account_id}'.\\nRun 'but config forge auth' to re-authenticate.\"\n            )\n            .context(NOT_AUTHENTICATED))\n        }\n    }\n\n    pub async fn get_authenticated(&self) -> Result<AuthenticatedUser> {\n        let url = format!(\"{}/user\", self.base_url);\n        let response = self.client.get(&url).send().await?;\n\n        if !response.status().is_success() {\n            return Err(HttpStatusError {\n                status: response.status(),\n            }\n            .into());\n        }\n\n        let user: BitbucketApiUser = response.json().await?;","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-bitbucket/src/client.rs#L46-L82","documentation":"`BitbucketClient::from_storage` builds an authenticated client for a Bitbucket account. If no OAuth access token is stored for the resolved account, it returns this error with the NOT_AUTHENTICATED code, instructing the user to re-authenticate via `but config forge auth`.","triggerScenarios":"Calling any Bitbucket client construction (`from_storage`) for an account whose token was never stored, was deleted, or was revoked/invalidated in storage.","commonSituations":"Token revoked on Bitbucket's side; `but config forge auth` never run for this account; local credentials storage cleared or migrated; using a preferred account ID that exists but has no token.","solutions":["Run `but config forge auth` to re-authenticate with Bitbucket","Verify the account ID is correct if a preferred account was specified","Check stored forge credentials/token storage for corruption or a cleared keychain","Re-add the Bitbucket account to the forges configuration"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// check a token exists before constructing the client\nlet has_token = but_bitbucket::token::get_bb_access_token(&account_id, storage)?\n    .is_some();\nif !has_token {\n    eprintln!(\"run 'but config forge auth' first\");\n}","typeGuard":null,"tryCatchPattern":"match BitbucketClient::from_storage(storage, preferred) {\n    Err(e) if e.downcast_ref::<api_error>() .map(|c| c.code == \"NOT_AUTHENTICATED\").unwrap_or(false)\n        || format!(\"{e:#}\").contains(\"No Bitbucket access token\") =>\n    {\n        prompt_forge_auth();\n        Err(e)\n    }\n    other => other,\n}","preventionTips":["Run `but config forge auth` after installing or clearing storage","Detect revoked tokens and proactively re-authenticate","Validate the account ID before selecting a preferred account"],"tags":["bitbucket","authentication","oauth","token"],"backgroundTag":"authentication-required","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"}