zed-industries/zed · error · anyhow::Error

{e}

Error message

{e}

What it means

The MCP tool's input never arrived: `input.recv()` failed because the sending side of the tool-input channel was dropped without sending a value. The error string is the receive error ('channel closed'). In practice the agent loop aborted the tool call — run cancelled, thread shutdown, or the call discarded upstream — before delivering input.

Source

Thrown at crates/agent/src/tools/context_server_registry.rs:358

        input: ToolInput<serde_json::Value>,
        event_stream: ToolCallEventStream,
        cx: &mut App,
    ) -> Task<Result<AgentToolOutput, AgentToolOutput>> {
        let Some(server) = self.store.read(cx).get_running_server(&self.server_id) else {
            return Task::ready(Err(anyhow::anyhow!("Context server not found").into()));
        };
        let tool_name = self.tool.name.clone();
        let tool_id = mcp_tool_id(&self.server_id.0, &self.tool.name);
        let display_name = self.tool.name.clone();
        let initial_title = self.initial_title(serde_json::Value::Null, cx);
        let authorize =
            event_stream.authorize_third_party_tool(initial_title, tool_id, display_name, cx);

        cx.spawn(async move |cx| {
            let input = input
                .recv()
                .await
                .map_err(|e| anyhow::anyhow!(e.to_string()))?;

            authorize
                .await
                .map_err(|e| anyhow::anyhow!(e.to_string()))?;

            let Some(protocol) = server.client() else {
                return Err(anyhow::anyhow!("Context server not initialized").into());
            };

            let arguments = if let serde_json::Value::Object(map) = input {
                Some(map.into_iter().collect())
            } else {
                None
            };

            log::trace!(
                "Running tool: {} with arguments: {:?}",
                tool_name,

View on GitHub (pinned to bc538def45)

Solutions

  1. Map it to 'tool call aborted' — never retry the MCP call with empty or guessed input.
  2. Ensure callers either send input or cancel explicitly, and that cancellation propagates cleanly.
  3. In tests, always supply a ready input value instead of a dropped channel.

Example fix

// before
let input = input.recv().await.map_err(|e| anyhow::anyhow!(e.to_string()))?;
// after
let input = match input.recv().await {
    Ok(value) => value,
    Err(_) => return Err(anyhow::anyhow!("tool input dropped — call was aborted").into()),
};
Defensive patterns

Strategy: try-catch

Try / catch

let input = match input.recv().await {
    Ok(value) => value,
    Err(_) => return Err(anyhow::anyhow!("tool call aborted before input arrived").into()),
};

Prevention

When it happens

Trigger: Cancelling the agent run or dropping the `ToolInput` sender between tool dispatch and input delivery; upstream errors that abandon the call; tests that construct the tool without ever providing input.

Common situations: Stop pressed right as a tool call starts; agent thread torn down mid-dispatch; streaming-input pipelines that error before the first value.

Related errors


AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16). Data as JSON: /api/errors/9af283926f76234f. Report an issue: GitHub.