xai-org/grok-build · error

failed to build request: {e}

Error message

failed to build request: {e}

What it means

This error is raised by `ext_call` in the worktree command module when `ext_request` cannot construct the JSON-RPC request for an ACP extension method call. The underlying cause is a serialization failure of the `params` argument or an invalid method string, wrapped via anyhow with the original formatter error. It aborts the worktree subcommand before anything is sent over the ACP transport.

Source

Thrown at crates/codegen/xai-grok-pager/src/worktree_cmd/mod.rs:139

    method: &str,
    params: &T,
) -> Result<acp::ExtRequest, serde_json::Error> {
    let params = serde_json::value::to_raw_value(params)?;
    Ok(acp::ExtRequest::new(method, params.into()))
}
/// ACP extension responses are wrapped in `{ "result": T, "error": ... }`.
#[derive(serde::Deserialize)]
struct ExtEnvelope<T> {
    result: Option<T>,
    error: Option<serde_json::Value>,
}
async fn ext_call<T: serde::de::DeserializeOwned>(
    tx: &xai_acp_lib::AcpAgentTx,
    method: &str,
    params: &impl serde::Serialize,
) -> Result<T> {
    let req =
        ext_request(method, params).map_err(|e| anyhow::anyhow!("failed to build request: {e}"))?;
    let resp = acp_send(req, tx)
        .await
        .map_err(|e| anyhow::anyhow!("{e}"))?;
    let envelope: ExtEnvelope<T> = serde_json::from_str(resp.0.get())
        .map_err(|e| anyhow::anyhow!("response parse error: {e}"))?;
    if let Some(err) = envelope.error {
        bail!("ACP error: {err}");
    }
    envelope
        .result
        .ok_or_else(|| anyhow::anyhow!("ACP response missing result field"))
}
async fn cmd_list(
    tx: &xai_acp_lib::AcpAgentTx,
    repo: Option<String>,
    types: Vec<String>,
    json: bool,
    all: bool,

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Inspect the inner `{e}` message to identify which params field failed to serialize.
  2. Check the params struct for types serde_json cannot represent (non-string map keys, f64::NAN, untagged enums that fail).
  3. Replace HashMap keys with String or BTreeMap<String, T> in the params type.
  4. Add a Serialize derive/unit test that round-trips the params struct to catch regressions early.

Example fix

// before
let params = serde_json::Map::new(); // built with non-string keys somewhere upstream
// after
#[derive(serde::Serialize)]
struct WorktreeListParams { repo: Option<String>, types: Vec<String> }
let params = WorktreeListParams { repo, types }; // guaranteed serializable
Defensive patterns

Strategy: validation

Validate before calling

fn assert_serializable<T: serde::Serialize>(params: &T) -> Result<(), String> {
    serde_json::to_value(params).map(|_| ()).map_err(|e| e.to_string())
}
// call before ext_call: assert_serializable(&params)?;

Try / catch

match ext_call::<WorktreeList>(tx, "worktree/list", &params).await {
    Ok(list) => render(list),
    Err(e) if e.to_string().contains("failed to build request") => {
        eprintln!("params serialization failed: {e:#}");
    }
    Err(e) => eprintln!("worktree command failed: {e:#}"),
}

Prevention

When it happens

Trigger: Calling any worktree subcommand (list, show, rm, gc, db) whose params type fails `serde_json::to_value` serialization inside `ext_request`, e.g. params containing a non-string map key or a value serde_json rejects (NaN, non-string keys).

Common situations: A newly added CLI flag introduces a params field that fails to serialize; a params struct uses HashMap with non-string keys; serde feature mismatch after a dependency version change makes a field unserializable.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/cbada171066a8b19. Report an issue: GitHub.