{"record":{"id":"a637a777b2f7644a","repo":"BoundaryML/baml","slug":"failed-to-refresh-access-token","errorCode":null,"errorMessage":"Failed to refresh access token: {}","messagePattern":"Failed to refresh access token: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/cli/src/propelauth.rs","lineNumber":331,"sourceCode":"\n        Ok(&self.access_token)\n    }\n\n    async fn refresh_access_token(&mut self) -> Result<RefreshAccessTokenResponse> {\n        let client = PropelAuthClient::new()?;\n        let response = client\n            .post(\"/propelauth/oauth/token\")\n            .header(\"Content-Type\", \"application/x-www-form-urlencoded\")\n            .form(&[\n                (\"client_id\", client.client_id.as_str()),\n                (\"refresh_token\", self.refresh_token.as_str()),\n                (\"grant_type\", \"refresh_token\"),\n            ])\n            .send()\n            .await?;\n\n        if !response.status().is_success() {\n            anyhow::bail!(\"Failed to refresh access token: {}\", response.text().await?);\n        }\n\n        let body: RefreshAccessTokenResponse = response\n            .json()\n            .await\n            .context(\"Failed to parse refresh access token response\")?;\n\n        Ok(body)\n    }\n\n    pub(crate) fn read_from_storage() -> Result<Self> {\n        let creds_path = app_strategy()\n            .context(\"Unable to get project directories\")?\n            .in_config_dir(\"creds.json\");\n\n        // TODO: if these fail we should tell the user to login\n        if !creds_path.exists() {\n            anyhow::bail!(\"No credentials found\");","sourceCodeStart":313,"sourceCodeEnd":349,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/cli/src/propelauth.rs#L313-L349","documentation":"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.","triggerScenarios":"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.","commonSituations":"User logged out elsewhere invalidating the session; credentials file stale after a long time; server-side token rotation; clock/config issues.","solutions":["Run `baml login` again to obtain fresh credentials (this replaces creds.json)","Delete the stored credentials file (in the config dir, creds.json) and re-login","Verify no corporate proxy intercepts the auth endpoint; retry the command"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await command();\n} catch (e) {\n  if (String(e).includes('Failed to refresh access token')) {\n    execSync('baml login'); // re-authenticate\n    await command();\n  }\n}","preventionTips":["Re-login periodically; refresh tokens expire","Log out/in cleanly after changing devices","Check network/proxy access to the auth server"],"tags":["oauth","auth","token-refresh","network"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}