Hmbown/CodeWhale · error

MCP operation on plugin server

Error message

MCP operation on plugin server '{}' was cancelled after authority changed: {reason}

What it means

While an MCP plugin-server operation was in flight, the authority state for that plugin changed (a shared cancellation flag became set). The client shuts down the transport, marks the connection disconnected, and cancels the operation with this error carrying the human-readable reason for the authority change.

Solutions

  1. Re-read the reason string, address the authority change (re-authorize or re-enable the plugin), then retry.
  2. Avoid starting plugin MCP operations concurrently with plugin enable/disable or permission changes.
  3. Handle this error as a cancellation, not a transport bug: reconnect only after authority is settled.
Defensive patterns

Strategy: try-catch

Validate before calling

if plugin_authority_was_revoked(server_name) {
    // skip the call; authority changed before we started
    return Ok(Cancelled);
}

Try / catch

match conn.call(...).await {
    Err(e) if e.to_string().contains("cancelled after authority changed") => {
        // treat as cancellation: do not retry until the plugin is re-authorized
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling an McpConnection method on a plugin server while another component revokes/changes that plugin's authority (e.g. plugin disable, permission change, workspace switch) setting the shared cancellation reason.

Common situations: User disables or re-authorizes a plugin mid-operation; workspace or trust-level change invalidates the plugin's grant while a tool call is running.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

    }

    fn catalog_authorized(&self) -> bool {
        self.config
            .reviewed_plugin
            .as_ref()
            .is_none_or(ReviewedPluginMcpSource::catalog_is_current)
    }

    async fn finish_guarded_error<T>(&mut self, error: anyhow::Error) -> Result<T> {
        let reason = self
            .authority_revocation_reason
            .lock()
            .ok()
            .and_then(|reason| reason.clone());
        if let Some(reason) = reason {
            self.transport.shutdown().await;
            self.state = ConnectionState::Disconnected;
            anyhow::bail!(
                "MCP operation on plugin server '{}' was cancelled after authority changed: {reason}",
                self.name
            );
        }
        Err(error)
    }
}

/// Resolve the operator's proxy route for this exact request using the same
/// matcher as reqwest. A NO_PROXY match returns None: direct requests must keep
/// their public DNS validation and pins. Model and reviewed-plugin requests
/// return before even reading proxy credentials.
fn configured_mcp_proxy<F>(
    url: &reqwest::Url,
    disallow_ambient_proxy: bool,
    mut read_environment: F,
) -> Result<Option<reqwest::Proxy>>
where

View on GitHub (pinned to 73e0f67d83)