{"record":{"id":"5aed354c530425e8","repo":"Hmbown/CodeWhale","slug":"mcp-operation-on-plugin-server-was-cancelled","errorCode":null,"errorMessage":"MCP operation on plugin server '{}' was cancelled after authority changed: {reason}","messagePattern":"MCP operation on plugin server '(.+?)' was cancelled after authority changed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":2485,"sourceCode":"    }\n\n    fn catalog_authorized(&self) -> bool {\n        self.config\n            .reviewed_plugin\n            .as_ref()\n            .is_none_or(ReviewedPluginMcpSource::catalog_is_current)\n    }\n\n    async fn finish_guarded_error<T>(&mut self, error: anyhow::Error) -> Result<T> {\n        let reason = self\n            .authority_revocation_reason\n            .lock()\n            .ok()\n            .and_then(|reason| reason.clone());\n        if let Some(reason) = reason {\n            self.transport.shutdown().await;\n            self.state = ConnectionState::Disconnected;\n            anyhow::bail!(\n                \"MCP operation on plugin server '{}' was cancelled after authority changed: {reason}\",\n                self.name\n            );\n        }\n        Err(error)\n    }\n}\n\n/// Resolve the operator's proxy route for this exact request using the same\n/// matcher as reqwest. A NO_PROXY match returns None: direct requests must keep\n/// their public DNS validation and pins. Model and reviewed-plugin requests\n/// return before even reading proxy credentials.\nfn configured_mcp_proxy<F>(\n    url: &reqwest::Url,\n    disallow_ambient_proxy: bool,\n    mut read_environment: F,\n) -> Result<Option<reqwest::Proxy>>\nwhere","sourceCodeStart":2467,"sourceCodeEnd":2503,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/mcp.rs#L2467-L2503","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Re-read the reason string, address the authority change (re-authorize or re-enable the plugin), then retry.","Avoid starting plugin MCP operations concurrently with plugin enable/disable or permission changes.","Handle this error as a cancellation, not a transport bug: reconnect only after authority is settled."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if plugin_authority_was_revoked(server_name) {\n    // skip the call; authority changed before we started\n    return Ok(Cancelled);\n}","typeGuard":null,"tryCatchPattern":"match conn.call(...).await {\n    Err(e) if e.to_string().contains(\"cancelled after authority changed\") => {\n        // treat as cancellation: do not retry until the plugin is re-authorized\n    }\n    r => r?,\n}","preventionTips":["Serialize plugin authority changes (disable/revoke) with in-flight MCP operations.","Check plugin authorization state before issuing long-running plugin tool calls.","Surface the reason string to the user rather than treating it as a transport fault."],"tags":["mcp","plugin","cancellation","authorization"],"backgroundTag":"invalid-state-transition","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}