{"record":{"id":"5afd2aac12f71116","repo":"aaif-goose/goose","slug":"tool-call-request-not-found-for-elicitation","errorCode":null,"errorMessage":"Tool call request not found for elicitation: {}","messagePattern":"Tool call request not found for elicitation: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose/src/action_required_manager.rs","lineNumber":78,"sourceCode":"    }\n\n    pub(crate) async fn request_and_wait(\n        &self,\n        session_id: String,\n        tool_call_request_id: String,\n        message: String,\n        schema: Value,\n        timeout_duration: Duration,\n    ) -> Result<ElicitationOutcome> {\n        let sender = self\n            .action_required_senders\n            .lock()\n            .await\n            .get(&(session_id.clone(), tool_call_request_id.clone()))\n            .cloned();\n\n        let Some(sender) = sender else {\n            return Err(anyhow::anyhow!(\n                \"Tool call request not found for elicitation: {}\",\n                tool_call_request_id\n            ));\n        };\n\n        let id = Uuid::new_v4().to_string();\n        let (tx, rx) = tokio::sync::oneshot::channel();\n        let pending_request = PendingRequest {\n            session_id: session_id.clone(),\n            response_tx: Some(tx),\n        };\n        let pending_request = Arc::new(Mutex::new(pending_request));\n\n        self.pending\n            .write()\n            .await\n            .insert(id.clone(), Arc::clone(&pending_request));\n","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose/src/action_required_manager.rs#L60-L96","documentation":"request_elicitation looks up an mpsc sender registered under the key (session_id, tool_call_request_id) in action_required_senders; if no entry exists it fails immediately with this message. The registration is created when a tool call action-required stream is set up, so this error means the elicitation references a tool call that has no live message stream in that session.","triggerScenarios":"Responding to an elicitation for a tool_call_request_id from a different session, one whose session already ended and deregistered its sender, or a stale/expired request id retained by the client.","commonSituations":"Client keeps an old dialog open after the session restarted; tool call finished and its stream was removed, then a late elicitation response arrives; session ids mixed up in a multi-session client.","solutions":["Verify the tool_call_request_id belongs to an in-flight tool call in the same session before eliciting","Close/discard elicitation dialogs when the owning session or tool call completes","Re-issue the tool call if the elicitation is still relevant, producing a fresh request id with a live sender"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before eliciting, confirm the tool call still has a live sender for this session\nlet known: Vec<_> = manager.active_tool_call_ids(session_id).await; // expose keys for introspection\nif !known.contains(&tool_call_request_id) {\n    return Err(anyhow::anyhow!(\"tool call {tool_call_request_id} not active in session\"));\n}","typeGuard":null,"tryCatchPattern":"match manager.request_elicitation(sid, tcid, msg, schema, d).await {\n    Err(e) if e.to_string().contains(\"not found for elicitation\") => {\n        tracing::warn!(%e, \"stale tool call; re-issue it\");\n        retry_tool_call().await\n    }\n    r => r,\n}","preventionTips":["Bind elicitation dialogs to the owning session/tool call and clear them on completion","Never reuse tool_call_request_ids across sessions"],"tags":["elicitation","session","tool-call","stale-state"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}