aaif-goose/goose · warning
Request not found: {}
Error message
Request not found: {} What it means
Thrown by ActionRequiredManager::pending_request when the request_id is not present in the in-memory pending map. The map is populated by request_and_wait and the entry is removed as soon as the request completes, times out, or fails to enqueue — so an unknown id means the elicitation is no longer answerable (or never existed in this process).
Source
Thrown at crates/goose/src/action_required_manager.rs:157
.as_ref()
.ok_or_else(|| anyhow::anyhow!("Request already completed: {}", request_id))?;
if tx.is_closed() {
pending.response_tx.take();
return Err(anyhow::anyhow!("Response channel closed"));
}
Ok(PendingResponseClaim {
request_id: request_id.to_string(),
pending,
})
}
async fn pending_request(&self, request_id: &str) -> Result<Arc<Mutex<PendingRequest>>> {
let pending = self.pending.read().await;
pending
.get(request_id)
.cloned()
.ok_or_else(|| anyhow::anyhow!("Request not found: {}", request_id))
}
async fn wait_for_response(
&self,
request_id: &str,
pending_request: Arc<Mutex<PendingRequest>>,
mut rx: tokio::sync::oneshot::Receiver<ElicitationOutcome>,
timeout_duration: Duration,
) -> Result<ElicitationOutcome> {
match timeout(timeout_duration, &mut rx).await {
Ok(response) => Self::finish_waiting(request_id, response),
Err(_) => {
let mut pending = pending_request.lock().await;
if pending.response_tx.is_some() {
pending.response_tx.take();
warn!("Timeout waiting for response: {}", request_id);
return Err(anyhow::anyhow!("Timeout waiting for user response"));
}View on GitHub (pinned to 3810898a74)
Solutions
- Answer the elicitation once, within its lifetime — before it completes or times out
- Use the exact request id from the most recent action_required message in the live conversation, not one restored from an old session
- If the id is unknown, continue with a normal user message instead of an elicitation response
- Guard double-submits in the UI (disable the button after first answer)
Example fix
// before
let claim = manager.claim_response(&session_id, &request_id).await?;
// after
let claim = match manager.claim_response(&session_id, &request_id).await {
Ok(claim) => claim,
Err(e) if e.to_string().contains("Request not found") => {
// already answered, expired, or from a previous run — nothing to do
return Ok(());
}
Err(e) => return Err(e),
}; Defensive patterns
Strategy: try-catch
Validate before calling
// Only answer ids that appear as unanswered action_required messages in the
// live conversation:
let is_open = conversation.messages.iter().any(|m| {
m.content.iter().any(|c| matches!(c,
MessageContent::ActionRequiredElicitation { id, .. } if id == request_id))
}); Type guard
fn request_not_found(e: &anyhow::Error) -> bool {
e.to_string().contains("Request not found")
} Try / catch
match manager.claim_response(&session_id, &request_id).await {
Ok(claim) => { /* submit */ }
Err(e) if request_not_found(&e) => {
// already answered, expired, or from a previous process run — no-op
}
Err(e) => return Err(e),
} Prevention
- Never reuse elicitation ids from restored/resumed sessions in a new process
- Answer each elicitation exactly once
- Pass the id verbatim from the received action_required message
- Treat 'Request not found' as expected control flow, not a crash
When it happens
Trigger: Responding to an elicitation that already completed (entry removed after wait_for_response returns); responding after the waiter timed out and cleaned up (line self.pending.write().await.remove(&id)); using a request_id from a previous process run — the map is per-process and not restored from session history; typo'd or fabricated request_id.
Common situations: Double-submitting an elicitation answer (double-click on Accept/Decline in the UI); answering a stale action_required message reloaded from a resumed session after goose restarted; two UI clients answering the same request.
Related errors
- Tool call request not found for elicitation: {}
- Request {} belongs to session {}, not {}
- Timeout waiting for user response
- Extension state serialization failed: {}
- Failed to persist extension state: {}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/28118393fb9d6eeb.
Report an issue: GitHub.