gitbutlerapp/gitbutler · error

ForgeNotAuthenticated

ForgeNotAuthenticated

Error message

No GitLab access token found for account '{account_id}'.\nRun 'but config forge auth' to re-authenticate.

What it means

from_storage resolves the requested (or default) GitLab account and looks up its access token in forge storage; if no token is stored for that account id, it fails with ForgeNotAuthenticated. This means the account was never authenticated or its stored token was removed.

Solutions

  1. Run `but config forge auth` to re-authenticate with GitLab
  2. Verify which GitLab accounts are authenticated (but config forge) and align the preferred account id
  3. If tokens were wiped, re-run the OAuth flow for every account you use
Defensive patterns

Strategy: validation

Validate before calling

if crate::token::get_gl_access_token(&account_id, storage)?.is_none() {
    eprintln!("Run 'but config forge auth' to authenticate GitLab account {account_id}");
    return Ok(None);
}

Type guard

fn has_token(account_id: &GitlabAccountIdentifier, storage: &Controller) -> bool {
    crate::token::get_gl_access_token(account_id, storage).map(|t| t.is_some()).unwrap_or(false)
}

Prevention

When it happens

Trigger: Constructing the GitLab client via Client::from_storage when token::get_gl_access_token returns None for the resolved account_id — the account name resolved but no token exists in storage (expired cleanup, wiped token store, auth never completed).

Common situations: User authenticated a different GitLab account than the preferred one; token storage cleared or reinstalled; auth flow aborted midway so no token was persisted.

Understand the failure class

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/30bec2a741b8362c. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-gitlab/src/client.rs:79

            .default_headers(headers)
            .timeout(GITLAB_REQUEST_TIMEOUT)
            .build()?;

        Ok(Self {
            client,
            base_url: GITLAB_API_BASE_URL.to_string(),
        })
    }

    pub fn from_storage(
        storage: &but_forge_storage::Controller,
        preferred_account: Option<&crate::GitlabAccountIdentifier>,
    ) -> anyhow::Result<Self> {
        let account_id = resolve_account(preferred_account, storage)?;
        if let Some(access_token) = crate::token::get_gl_access_token(&account_id, storage)? {
            account_id.client(&access_token)
        } else {
            Err(anyhow::anyhow!(
                "No GitLab access token found for account '{account_id}'.\nRun 'but config forge auth' to re-authenticate."
            )
            .context(NOT_AUTHENTICATED))
        }
    }

    pub fn new_with_host_override(access_token: &Sensitive<String>, host: &str) -> Result<Self> {
        let mut headers = HeaderMap::new();
        headers.insert(
            USER_AGENT,
            HeaderValue::from_static("gb-gitlab-integration"),
        );
        headers.insert(ACCEPT, HeaderValue::from_static("application/json"));
        headers.insert(
            AUTHORIZATION,
            HeaderValue::from_str(&format!("Bearer {}", access_token.0))?,
        );

View on GitHub (pinned to 58e5313667)