BoundaryML/baml · error

Failed to refresh access token

Error message

Failed to refresh access token: {}

What it means

The CLI attempted to refresh its PropelAuth access token using the stored refresh token, and the auth server returned a non-success HTTP status. The error carries the raw response body, typically indicating an invalid or expired refresh token.

Solutions

  1. Run `baml login` again to obtain fresh credentials (this replaces creds.json)
  2. Delete the stored credentials file (in the config dir, creds.json) and re-login
  3. Verify no corporate proxy intercepts the auth endpoint; retry the command
Defensive patterns

Strategy: retry

Try / catch

try {
  await command();
} catch (e) {
  if (String(e).includes('Failed to refresh access token')) {
    execSync('baml login'); // re-authenticate
    await command();
  }
}

Prevention

When it happens

Trigger: access_token() detects the cached access token is expired and calls refresh_access_token(); the POST to the token endpoint with grant_type=refresh_token returns 400/401 because the refresh token is revoked, expired, or malformed.

Common situations: User logged out elsewhere invalidating the session; credentials file stale after a long time; server-side token rotation; clock/config issues.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/a637a777b2f7644a. Report an issue: GitHub.

Appendix: source

Thrown at engine/cli/src/propelauth.rs:331

        Ok(&self.access_token)
    }

    async fn refresh_access_token(&mut self) -> Result<RefreshAccessTokenResponse> {
        let client = PropelAuthClient::new()?;
        let response = client
            .post("/propelauth/oauth/token")
            .header("Content-Type", "application/x-www-form-urlencoded")
            .form(&[
                ("client_id", client.client_id.as_str()),
                ("refresh_token", self.refresh_token.as_str()),
                ("grant_type", "refresh_token"),
            ])
            .send()
            .await?;

        if !response.status().is_success() {
            anyhow::bail!("Failed to refresh access token: {}", response.text().await?);
        }

        let body: RefreshAccessTokenResponse = response
            .json()
            .await
            .context("Failed to parse refresh access token response")?;

        Ok(body)
    }

    pub(crate) fn read_from_storage() -> Result<Self> {
        let creds_path = app_strategy()
            .context("Unable to get project directories")?
            .in_config_dir("creds.json");

        // TODO: if these fail we should tell the user to login
        if !creds_path.exists() {
            anyhow::bail!("No credentials found");

View on GitHub (pinned to bd85ce9dee)