Hmbown/CodeWhale · error · anyhow::Error

MCP server ' ' is no longer configured

Error message

MCP server '{server_name}' is no longer configured

What it means

During the OAuth authenticate flow, the pool looks up the server config by name after the authentication tool call; if the server was removed from the current MCP config in the meantime, this error aborts the flow instead of authorizing against a server that no longer exists.

Solutions

  1. Re-check the server still exists in MCP config; re-add it if it was removed unintentionally
  2. Refresh the tool catalog so stale references to removed servers disappear
  3. If the removal was intentional, abandon the login — authorization for a removed server is meaningless
Defensive patterns

Strategy: validation

Validate before calling

// before starting an OAuth flow, confirm the server still exists
if pool.server_config(server_name).is_none() {
    anyhow::bail!("server '{server_name}' not configured; cannot authenticate");
}

Try / catch

match authenticate(server_name).await {
    Err(e) if e.to_string().contains("no longer configured") => refresh_catalog_and_recheck(server_name),
    other => other,
}

Prevention

When it happens

Trigger: Calling the server's authenticate tool (AUTHENTICATE_TOOL_NAME) for a server_name that is no longer present in config when server_config() is re-queried.

Common situations: User deletes the server from mcp.json (or a plugin providing it is uninstalled) while a browser-based OAuth login is in flight; stale tool catalog references a removed server.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/fd374411288f60ba. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/mcp.rs:3989

    /// config, the connection map, and the token store — it returns as soon
    /// as the authorization URL exists, so a caller holding the pool lock can
    /// release it before the (up to five minute) browser wait in
    /// [`oauth::McpOAuthToolLogin::finish`]. Holding the lock across that wait
    /// would freeze every other MCP call, the `/mcp` manager, and the
    /// Extensions view for the whole sign-in.
    pub(crate) async fn begin_authenticate_tool(
        &self,
        server_name: &str,
    ) -> Result<AuthenticateToolStart> {
        self.require_server(server_name)?;
        Self::authorize_call(
            &self.disallowed_tools,
            &Self::mcp_model_tool_name(server_name, AUTHENTICATE_TOOL_NAME),
            &serde_json::json!({}),
        )?;
        let server = self
            .server_config(server_name)
            .ok_or_else(|| anyhow::anyhow!("MCP server '{server_name}' is no longer configured"))?;
        if !server.is_enabled() {
            anyhow::bail!("MCP server '{server_name}' is disabled");
        }

        // Already-authorized branch: a login that completed since the catalog
        // was built (e.g. `codewhale mcp login` in another window) must not
        // restart the browser flow — adopt the stored tokens by reconnecting.
        let ready = self
            .connections
            .get(server_name)
            .is_some_and(McpConnection::is_ready);
        if ready || oauth::has_usable_stored_tokens(server_name, &server) {
            return Ok(AuthenticateToolStart::AlreadyAuthorized);
        }
        let login = oauth::begin_oauth_login_for_server_tool(
            server_name,
            &server,
            None,

View on GitHub (pinned to 73e0f67d83)