Kuberwastaken/claurst · error · anyhow::Error

Failed to store MCP token for

Error message

Failed to store MCP token for '{}': {}

What it means

After a successful OAuth flow completes, the resulting token is persisted via oauth::store_mcp_token. If persistence fails (I/O error, storage backend unavailable), the original error is wrapped with this message naming the server. The token may still be valid in memory but was not saved, so it will not survive the session.

Solutions

  1. Inspect the inner error text to see the underlying storage failure
  2. Check that the token/config directory exists and is writable by the process
  3. Re-run the auth flow once the storage issue is fixed — the token is not persisted
  4. Free disk space / resolve file locks if the store could not be written
Defensive patterns

Strategy: try-catch

Validate before calling

let dir = token_store_dir()?;
let probe = dir.join(".write-probe");
std::fs::write(&probe, b"ok").context("token store dir not writable")?;
let _ = std::fs::remove_file(&probe);

Try / catch

match oauth::store_mcp_token(&token) {
    Ok(()) => {}
    Err(e) => {
        eprintln!("warning: token for {server} not persisted: {e}; re-auth next session");
    }
}

Prevention

When it happens

Trigger: run_mcp_auth_flow() finished the browser flow but store_mcp_token(&mcp_token) returned Err — disk full, auth-store file locked/unwritable, storage directory missing, or serialization failure.

Common situations: Home directory or config dir not writable (sandboxed process, read-only FS); concurrent runs of the auth flow corrupting/locking the token store; disk quota exceeded; corrupted auth store file forcing rewrite failure.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/9dc6cb9cb020c3d4. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/mcp/src/lib.rs:1281

        token: &str,
        expires_in: Option<u64>,
    ) -> anyhow::Result<()> {
        let expires_at = expires_in.map(|secs| {
            std::time::SystemTime::now()
                .duration_since(std::time::UNIX_EPOCH)
                .unwrap_or_default()
                .as_secs()
                + secs
        });
        let mcp_token = oauth::McpToken {
            access_token: token.to_string(),
            refresh_token: None,
            expires_at,
            scope: None,
            server_name: server_name.to_string(),
        };
        oauth::store_mcp_token(&mcp_token)
            .map_err(|e| anyhow::anyhow!("Failed to store MCP token for '{}': {}", server_name, e))
    }

    /// Load the stored OAuth access token for an MCP server, if any.
    ///
    /// Returns `None` if no token is stored or the token cannot be refreshed.
    pub async fn load_token(&self, server_name: &str) -> Option<String> {
        let config = self.server_configs.get(server_name)?;
        let server_url = config.url.as_deref()?;
        oauth::get_valid_mcp_access_token(server_name, server_url)
            .await
            .ok()
            .flatten()
    }

    // -----------------------------------------------------------------------
    // Notification dispatch loop
    // -----------------------------------------------------------------------

View on GitHub (pinned to b0637c97ec)