zeroclaw-labs/zeroclaw · error · anyhow::Error
ACP elicitation/create failed
Error message
ACP elicitation/create failed: {} ({}) What it means
The JSON-RPC request elicitation/create itself returned an error response (message + code) instead of a result. This is the form-mode path used when the client advertises clientCapabilities.elicitation.form; the code and message embedded in the error come straight from the client, so they state why the elicitation was refused (method not implemented, invalid params, unknown sessionId).
Solutions
- Read the (code, message) pair embedded in the error text — it is the client's own stated reason for the refusal.
- Verify the session still exists on the client; re-run session/new and retry with a fresh sessionId if the client restarted.
- Confirm the client genuinely implements elicitation/create; if not, stop advertising elicitation.form so the legacy permission path is used.
- Align ZeroClaw and the client on protocol revisions that agree on the elicitation schema.
Defensive patterns
Strategy: try-catch
Type guard
fn client_supports_form_elicitation(caps: &ElicitationCapabilities) -> bool {
caps.form
} Try / catch
if let Err(e) = ch.request_choice(q, &choices, timeout).await {
if e.to_string().contains("elicitation/create failed") {
// client refused the prompt: re-create the session or surface
// 'could not ask the user' to the agent instead of retrying blindly
}
} Prevention
- Only advertise elicitation.form when elicitation/create is actually implemented
- Re-create the ACP session after client restarts instead of reusing session ids
- Integration-test the requestedSchema round-trip when bumping protocol versions
When it happens
Trigger: AcpChannel::request_choice on a form-capable client where elicitation/create is rejected: the client advertises elicitation.form but does not implement the handler, the sessionId is stale after a client restart, or the single-select requestedSchema fails the client's validation.
Common situations: Capability handshake lying (form advertised, handler missing); session id from a previous connection reused after reconnect; schema-shape drift between the ZeroClaw version emitting requestedSchema and the client version validating it.
Related errors
- ACP elicitation/create (multi) failed
- ACP elicitation/create timed out after
- ACP returned unexpected outcome
- ACP elicitation/create (multi) timed out after
- ACP returned unexpected permission outcome
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/8277a4c8fbd5cdb4.
Report an issue: GitHub.
Appendix: source
Thrown at crates/zeroclaw-channels/src/acp_channel.rs:150
timeout: Duration,
) -> anyhow::Result<Option<String>> {
let req = ElicitationRequest {
session_id: self.session_id.clone(),
mode: ElicitationMode::Form,
message: question.to_string(),
requested_schema: single_select_schema(choices),
};
debug_assert!(
matches!(req.mode, ElicitationMode::Form),
"Phase 1 must not emit URL-mode elicitation"
);
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 failed: {} ({})", e.message, e.code)
}
Err(_) => anyhow::bail!("ACP elicitation/create 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 text =
zeroclaw_api::elicitation::decode_single_select_accept(&content, choices)?;
Ok(Some(text))
}
ElicitationResponse::Decline | ElicitationResponse::Cancel => Ok(None),
}
}
}
impl ::zeroclaw_api::attribution::Attributable for AcpChannel {View on GitHub (pinned to 88bb9c8533)