aaif-goose/goose · error

Tool call action-required {message}: {tool_call_request_id}

Error message

Tool call action-required {message}: {tool_call_request_id}

What it means

After registering the pending request, request_elicitation pushes an action-required message onto the session's bounded mpsc stream with try_send. Failure means either 'stream is full' (channel at capacity, consumer not draining) or 'stream closed' (receiver dropped); the message text distinguishes which, and the pending entry is cleaned up before erroring.

Source

Thrown at crates/goose/src/action_required_manager.rs:106

            response_tx: Some(tx),
        };
        let pending_request = Arc::new(Mutex::new(pending_request));

        self.pending
            .write()
            .await
            .insert(id.clone(), Arc::clone(&pending_request));

        let action_required_message = Message::assistant().with_content(
            MessageContent::action_required_elicitation(id.clone(), message, schema),
        );
        if let Err(error) = sender.try_send(action_required_message) {
            self.pending.write().await.remove(&id);
            let message = match error {
                mpsc::error::TrySendError::Full(_) => "stream is full",
                mpsc::error::TrySendError::Closed(_) => "stream closed",
            };
            return Err(anyhow::anyhow!(
                "Tool call action-required {message}: {tool_call_request_id}"
            ));
        }

        let result = self
            .wait_for_response(&id, pending_request, rx, timeout_duration)
            .await;

        self.pending.write().await.remove(&id);

        result
    }

    pub(crate) async fn claim_response(
        &self,
        session_id: &str,
        request_id: &str,
    ) -> Result<PendingResponseClaim> {

View on GitHub (pinned to 3810898a74)

Solutions

  1. Ensure the session message stream is continuously consumed — keep the reader task alive while tool calls run
  2. If capacity is configurable, raise the channel size for workloads that burst many elicitation prompts
  3. Restart/reconnect the client so a fresh stream exists, then retry the tool call
Defensive patterns

Strategy: retry

Try / catch

match manager.request_elicitation(sid, tcid, msg, schema, d).await {
    Err(e) if e.to_string().contains("stream is full") => {
        tokio::time::sleep(Duration::from_millis(200)).await; // let consumer drain
        manager.request_elicitation(sid, tcid, msg, schema, d).await
    }
    Err(e) if e.to_string().contains("stream closed") => {
        tracing::warn!("client gone; aborting elicitation");
        Err(e)
    }
    r => r,
}

Prevention

When it happens

Trigger: The client stopped reading the session message stream (deadlocked or slow consumer) so the bounded channel fills; or the client disconnected and the stream receiver was dropped while the tool call tried to raise a permission prompt.

Common situations: Desktop/UI client stalled on a long render loop while many action-required prompts queue up; automation that creates tool calls without consuming the message stream; client crash mid-session.

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/73ee59c36da27ec1. Report an issue: GitHub.