zeroclaw-labs/zeroclaw · error · anyhow::Error
ACP elicitation/create (multi) timed out after {timeout:?}
Error message
ACP elicitation/create (multi) timed out after {timeout:?} What it means
The multi-select elicitation/create request got no answer before the caller-supplied timeout elapsed (tokio::time::timeout). Like the single-select path, this prevents an unresponsive client from parking the poll tool forever; the elapsed Duration is included in the message.
Source
Thrown at crates/zeroclaw-channels/src/acp_channel.rs:394
}
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!(
"ACP elicitation/create (multi) failed: {} ({})",
e.message,
e.code
),
Err(_) => {
anyhow::bail!("ACP 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 =
zeroclaw_api::elicitation::decode_multi_select_accept(&content, choices)?;
Ok(Some(texts))
}
ElicitationResponse::Decline | ElicitationResponse::Cancel => Ok(None),
}
}
/// Delegates to [`Self::request_approval_attributed`] and drops the
/// provenance, so the prompt logic lives in exactly one place.
async fn request_approval(View on GitHub (pinned to 88bb9c8533)
Solutions
- Raise the timeout passed to request_multi_choice to fit human form-filling time.
- Check that the ACP client and transport are alive before issuing the prompt.
- Treat the timeout as a cancellation (None) in the caller instead of an error, if proceeding without the selection is safe.
- Cancel in-flight prompts during session teardown so timeouts do not race shutdown.
Defensive patterns
Strategy: retry
Try / catch
match ch.request_multi_choice(q, &choices, min, max, timeout).await {
Ok(opt) => opt,
Err(e) if e.to_string().contains("timed out") => {
tracing::warn!(error = %e, "multi-select timed out; treating as declined");
None
}
Err(e) => return Err(e),
} Prevention
- Give multi-select forms longer timeouts than single-select
- Prompt only when the client is known responsive
- Cancel outstanding prompts during session teardown
When it happens
Trigger: request_multi_choice on a form-capable client where no JSON-RPC response arrives in time — the user never submits the multi-select form, the client exits, or the transport stalls.
Common situations: Multi-select forms left open because users must check several items; unattended sessions; network drops mid-prompt; timeouts copied from single-select defaults that are too short.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- ACP elicitation/create timed out after {timeout:?}
- ACP elicitation/create (multi) failed: {} ({})
- ACP elicitation/create failed: {} ({})
- AcpChannel.request_multi_choice requires at least one choice
- ACP request_permission timed out after {:?}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/74e43895d9971ffa.
Report an issue: GitHub.