zed-industries/zed · error

Failed to send tool call decision prompt: {error}

Error message

Failed to send tool call decision prompt: {error}

What it means

For tool calls that need an explicit decision, the thread sends a ToolCallAuthorization event with ActionChoice options; if that send fails, the event receiver is gone and this error wraps the failure. The decision prompt is undeliverable, so the gated action fails.

Source

Thrown at crates/agent/src/thread.rs:6368

            if let Some(message) = message {
                fields = fields.content(vec![acp::ToolCallContent::from(message)]);
            }

            let (response_tx, response_rx) = oneshot::channel();
            if let Err(error) = stream
                .0
                .unbounded_send(Ok(ThreadEvent::ToolCallAuthorization(
                    ToolCallAuthorization {
                        tool_call: acp::ToolCallUpdate::new(tool_call_id.clone(), fields),
                        options,
                        response: response_tx,
                        context: None,
                        kind: acp_thread::AuthorizationKind::ActionChoice,
                    },
                )))
            {
                log::error!("Failed to send tool call decision prompt: {error}");
                return Err(anyhow!("Failed to send tool call decision prompt: {error}"));
            }

            let outcome = response_rx
                .await
                .map_err(|_| anyhow!("authorization channel closed"))?;
            ensure_tool_call_authorization_not_interrupted(&outcome)?;
            Ok(outcome.option_id)
        })
    }

    /// Prompts the user for authorization.
    ///
    /// When `check_settings` is `Some`, this gate is settings-driven: the
    /// settings are evaluated up-front (an Allow or Deny result resolves the
    /// task immediately without prompting), and while a prompt is pending a
    /// `SettingsStore` subscription watches for changes. A subsequent Allow
    /// or Deny dismisses the prompt UI and resolves the task without user
    /// interaction.

View on GitHub (pinned to bc538def45)

Solutions

  1. Hold the ThreadEvent receiver until the thread is finished
  2. Handle the error as cancellation and abort the pending tool call
  3. Re-create the session and resend if the user still wants the action
  4. Cancel the thread before closing the UI so decision prompts resolve as cancelled turns
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(err) = decision_prompt_result {
    if err.to_string().starts_with("Failed to send tool call decision prompt") {
        // Event consumer is gone: treat as cancellation of the gated action.
        abort_pending_tool_call();
        return Ok(());
    }
    return Err(err);
}

Prevention

When it happens

Trigger: The thread's event consumer is dropped at the moment a tool call decision prompt (for example a continue/stop choice) is being sent.

Common situations: Closing the UI exactly when a decision is requested; client disconnects; embedding code scoping the event receiver too narrowly.

Related errors


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