Hmbown/CodeWhale · error
unexpected MCP OAuth state while preparing stored credential
Error message
unexpected MCP OAuth state while preparing stored credentials
What it means
When restoring persisted MCP OAuth credentials, a fresh OAuthState is created and set_credentials installs the stored client ID and token response; afterwards the state must have settled into Authorized or Unauthorized to yield a usable manager. Any other enum variant (e.g. a mid-flow state such as Session) means the stored credentials do not map onto a settled state, and construction aborts with this bail.
Source
Thrown at crates/tui/src/mcp/oauth.rs:187
async fn from_stored_tokens(
server_name: &str,
url: &str,
mut tokens: StoredMcpOAuthTokens,
default_headers: HeaderMap,
) -> Result<Self> {
refresh_expires_in_from_timestamp(&mut tokens);
let client = apply_default_headers(crate::tls::reqwest_client_builder(), &default_headers)
.build()
.context("building MCP OAuth metadata client")?;
let mut state = OAuthState::new(url.to_string(), Some(client)).await?;
state
.set_credentials(&tokens.client_id, tokens.token_response.0.clone())
.await
.context("installing stored MCP OAuth credentials")?;
let manager = match state {
OAuthState::Authorized(manager) | OAuthState::Unauthorized(manager) => manager,
_ => bail!("unexpected MCP OAuth state while preparing stored credentials"),
};
Ok(Self {
inner: Arc::new(McpOAuthRuntimeInner {
server_name: server_name.to_string(),
url: url.to_string(),
manager: Arc::new(Mutex::new(manager)),
last_tokens: Mutex::new(Some(tokens)),
}),
})
}
pub async fn authorization_header(&self) -> Result<Option<String>> {
self.refresh_if_needed().await?;
let credentials = {
let guard = self.inner.manager.lock().await;
let (_client_id, credentials) = guard
.get_credentials()View on GitHub (pinned to 0c42157ee5)
Solutions
- Clear the stored MCP OAuth credentials for that server (remove the token cache entry)
- Re-run the OAuth login flow to write fresh, fully-settled credentials
- Verify the stored token JSON matches the current credentials schema if it was migrated between versions
Example fix
# before: stale stored credentials keep OAuthState mid-flow rm ~/.local/state/codewhale/mcp-oauth/<server>.json # adjust to your token cache path codewhale mcp oauth login <server>
Defensive patterns
Strategy: fallback
Try / catch
match McpOAuthRuntime::with_stored_credentials(server_name, url, default_headers, tokens).await {
Ok(rt) => rt,
Err(e) if e.to_string().contains("unexpected MCP OAuth state") => {
// stored credentials are unusable: discard and fall back to a fresh login
clear_stored_mcp_oauth_tokens(server_name);
run_oauth_login(server_name, server).await?
}
Err(e) => return Err(e),
} Prevention
- Clear stored MCP OAuth credentials after version upgrades if login fails to initialize
- Persist tokens only after the OAuth flow fully settles, never mid-flow
- Treat token-cache schema changes as a migration step with a clean re-login fallback
When it happens
Trigger: Stored credentials were persisted mid-flow, are from an older format/version whose state transitions differ, or are corrupted such that set_credentials leaves the state machine in a non-settled variant.
Common situations: Upgrading the app with a stale token cache; an interrupted OAuth login leaving partial state; hand-edited or migrated token storage.
Related errors
- Kimi CLI credential import is unsupported. Codewhale does no
- Reviewed plugin MCP authentication failed (provider details
- OAuth is disabled for plugin-contributed MCP servers; use a
- stored MCP OAuth token for '{server_name}' is not valid cred
- Kimi is API-key-only in Codewhale. Create a key at https://p
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/cb458db4fe5c5e8c.
Report an issue: GitHub.