xai-org/grok-build · error
failed to build request
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.
Solutions
- Inspect the inner `{e}` message to identify which params field failed to serialize.
- Check the params struct for types serde_json cannot represent (non-string map keys, f64::NAN, untagged enums that fail).
- Replace HashMap keys with String or BTreeMap<String, T> in the params type.
- 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(¶ms)?; Try / catch
match ext_call::<WorktreeList>(tx, "worktree/list", ¶ms).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
- Keep params types to serde_json-friendly shapes (String keys, no NaN floats).
- Add round-trip serialization unit tests for every extension params struct.
- Wrap ext_request in a debug assertion during CI to catch serialization issues before release.
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.
Appendix: 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)