zeroclaw-labs/zeroclaw · error
RPC elicitation/create (multi) timed out after {timeout:?}
Error message
RPC elicitation/create (multi) timed out after {timeout:?} What it means
The multi-select elicitation call `elicitation/create` did not complete within the caller-supplied timeout (tokio::time::timeout elapsed). The connected client never answered the form and the connection did not surface an error, so the runtime gives up rather than blocking the approval flow indefinitely.
Source
Thrown at crates/zeroclaw-runtime/src/rpc/approval_channel.rs:278
timeout: Duration,
) -> anyhow::Result<Option<Vec<String>>> {
let req = ElicitationRequest {
session_id: self.session_id.clone(),
mode: ElicitationMode::Form,
message: question.to_string(),
requested_schema: multi_select_schema(choices, min_items, max_items),
};
let params = serde_json::to_value(&req)?;
let call = self.rpc.request("elicitation/create", params);
let response_value = match tokio::time::timeout(timeout, call).await {
Ok(Ok(value)) => value,
Ok(Err(e)) => anyhow::bail!(
"RPC elicitation/create (multi) failed: {} ({})",
e.message,
e.code
),
Err(_) => {
anyhow::bail!("RPC elicitation/create (multi) timed out after {timeout:?}")
}
};
let parsed: ElicitationResponse = serde_json::from_value(response_value)
.map_err(|e| anyhow::Error::msg(format!("malformed elicitation response: {e}")))?;
match parsed {
ElicitationResponse::Accept { content } => {
let texts = decode_multi_select_accept(&content, choices)?;
Ok(Some(texts))
}
ElicitationResponse::Decline | ElicitationResponse::Cancel => Ok(None),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;View on GitHub (pinned to 88bb9c8533)
Solutions
- Increase the timeout passed to request_multi_choice to match the expected human response window.
- Verify client connectivity (heartbeats/pings) before issuing the ask.
- Ensure the client event loop is not blocked while a form is pending.
- Treat timeout as 'no selection' (the single-select approval path maps timeout to Deny/TimedOut) and decide the fallback behavior explicitly.
Example fix
// before
let picks = channel
.request_multi_choice(q, &choices, 1, 3, Duration::from_secs(30))
.await?;
// after — allow a real operator window, treat timeout as no selection
match channel
.request_multi_choice(q, &choices, 1, 3, Duration::from_secs(300))
.await
{
Ok(Some(picks)) => { /* proceed */ }
Ok(None) => { /* declined/cancelled */ }
Err(e) if e.to_string().contains("timed out") => {
tracing::warn!("elicitation timed out; continuing without selection");
}
Err(e) => return Err(e),
} Defensive patterns
Strategy: retry
Validate before calling
// Before asking, confirm the client recently answered a ping/heartbeat // and size the timeout to the human response window, not a network RTT.
Try / catch
Err(e) if e.to_string().contains("(multi) timed out") => {
// one retry for a stalled-but-alive connection, then treat as no-selection
} Prevention
- Choose timeouts based on expected human decision time (minutes, not seconds).
- Monitor client liveness (heartbeats) before issuing blocking prompts.
- Decide and document the denial behavior on timeout so the workflow cannot hang.
When it happens
Trigger: Operator is away or the client UI never renders the request; the websocket/stdio connection stalls without closing (NAT drop, suspended laptop); the client event loop is blocked so the response is produced but never delivered; timeout set shorter than realistic human response time.
Common situations: Short approval timeouts (e.g. 30s) used with human-in-the-loop prompts; client on an unstable network; backgrounded TUI/mobile client that stops pumping messages; load-test clients that never answer elicitations.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- RPC elicitation/create timed out after {timeout:?}
- RPC elicitation/create (multi) failed: {} ({})
- ACP elicitation/create timed out after {timeout:?}
- ACP elicitation/create (multi) timed out after {timeout:?}
- ACP request_permission timed out after {:?}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/863ccfbcb4ed13b0.
Report an issue: GitHub.