zeroclaw-labs/zeroclaw · error

RPC elicitation/create (multi) failed: {} ({})

Error message

RPC elicitation/create (multi) failed: {} ({})

What it means

The multi-select elicitation request sent over JSON-RPC (`elicitation/create`) came back with a protocol-level error object (message + code) from the gateway/client. This is the peer rejecting the request itself — unknown method, rejected schema, unknown session — not the operator declining the form (Decline/Cancel return Ok(None)). The runtime bails with the peer's message and code verbatim so callers can distinguish a broken/unsupported channel from a user decision.

Source

Thrown at crates/zeroclaw-runtime/src/rpc/approval_channel.rs:272

    async fn request_multi_choice_via_elicitation(
        &self,
        question: &str,
        choices: &[String],
        min_items: usize,
        max_items: usize,
        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),
        }
    }

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Check the code in the message: -32601 (method not found) means the peer lacks elicitation support — upgrade the client/gateway or fall back to the plain approval/single-select path.
  2. Verify the session_id on the channel matches a live session on the gateway.
  3. Validate bounds before calling: min_items <= choices.len() and max_items >= min_items, and choices non-empty.
  4. Inspect gateway logs for the rejected elicitation payload if the code is a schema/validation error.

Example fix

// before
let picks = channel.request_multi_choice("Pick tools", &choices, 1, 3, timeout).await?;

// after — validate bounds, degrade gracefully when the peer rejects elicitation
if choices.is_empty() || min_items > choices.len() || max_items < min_items {
    anyhow::bail!("invalid multi-select bounds");
}
let picks = match channel.request_multi_choice("Pick tools", &choices, 1, 3, timeout).await {
    Ok(Some(v)) => v,
    Ok(None) => vec![], // operator declined
    Err(e) if e.to_string().starts_with("RPC elicitation/create") => {
        tracing::warn!("peer rejected elicitation, denying: {e}");
        vec![]
    }
    Err(e) => return Err(e),
};
Defensive patterns

Strategy: try-catch

Validate before calling

let bounds_ok = !choices.is_empty() && min_items <= choices.len() && max_items >= min_items;
if !bounds_ok { /* fix inputs before calling */ }

Try / catch

match channel.request_multi_choice(...).await {
    Ok(Some(v)) => { /* proceed */ }
    Ok(None) => { /* operator declined: safe default */ }
    Err(e) if e.to_string().starts_with("RPC elicitation/create (multi) failed") => {
        // peer rejected the request: log code/message, degrade to deny or fallback UI
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling request_multi_choice on a channel whose client does not implement elicitation/create (method-not-found), passing a stale or unknown session_id, or sending a multi_select_schema whose min_items/max_items or enum violates the peer's JSON-schema acceptance rules (e.g. min_items > choices.len(), max_items = 0).

Common situations: Client or gateway version predates elicitation support; the session disconnected or expired between channel setup and the ask; a strict validator on the client rejects the schema; only the single-select path is implemented by the connected UI.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/b5a1313790902ded. Report an issue: GitHub.