xai-org/grok-build · error · ToolError
Failed to build request: {e}
Error message
Failed to build request: {e} What it means
After the web search tool is built, the client assembles the full responses-API request (model, input, tools, temperature, top_p, max_output_tokens) via CreateResponseArgs and calls .build(). If the builder rejects the assembled arguments it maps the error to "Failed to build request: {e}". This is a client-side request construction failure; no request ever reaches the network.
Source
Thrown at crates/codegen/xai-grok-tools/src/implementations/web_search/client.rs:165
xai_tool_runtime::ToolError::execution(
xai_tool_protocol::ToolId::new("web_search").expect("valid"),
msg,
)
};
let web_search = rs::WebSearchToolArgs::default()
.filters(rs::WebSearchToolFilters { allowed_domains })
.build()
.map_err(|e| err(format!("Failed to build web search tool: {e}")))?;
let request = rs::CreateResponseArgs::default()
.model(self.model.clone())
.input(query.to_string())
.tools(vec![rs::Tool::WebSearch(web_search)])
.store(false)
.temperature(0.1)
.top_p(0.95)
.max_output_tokens(8192u32)
.build()
.map_err(|e| err(format!("Failed to build request: {e}")))?;
let mut body = serde_json::to_value(&request)
.map_err(|e| err(format!("Failed to serialize request: {e}")))?;
if let Some(excluded) = excluded_domains.filter(|d| !d.is_empty()) {
let tool = body
.get_mut("tools")
.and_then(|t| t.as_array_mut())
.and_then(|arr| arr.first_mut())
.and_then(|t| t.as_object_mut());
if let Some(tool) = tool {
let filters = tool
.entry("filters")
.or_insert_with(|| serde_json::json!({}));
filters["excluded_domains"] = serde_json::json!(excluded);
}
}
Ok(body)
}
/// Wire a 401-attribution callback into this client. Idempotent;View on GitHub (pinned to bc7f02eddd)
Solutions
- Read the wrapped {e} message to identify which builder field was rejected.
- Verify self.model is a valid, non-empty model identifier supported by the responses API.
- Check the rs crate changelog for CreateResponseArgs changes and update the construction accordingly.
- Build a minimal request (model + input + tool only) to isolate which optional field triggers the failure.
Example fix
// before
let client = WebSearchClient::new("")?; // empty model
// after
let client = WebSearchClient::new("gpt-4o")?; // valid model id Defensive patterns
Strategy: validation
Validate before calling
function validateSearchRequestArgs(model) {
if (typeof model !== 'string' || model.trim().length === 0) {
throw new Error('search requires a non-empty model identifier');
}
return true;
} Try / catch
try {
result = await client.search(query);
} catch (e) {
if (String(e).startsWith('Failed to build request')) {
// surface the wrapped builder message to config owners
throw new Error('Web search request config invalid: ' + e.message);
} else { throw e; }
} Prevention
- Keep the model identifier in validated configuration; reject empty/unknown values at startup.
- Test request construction with a minimal args set in CI after every rs crate upgrade.
- Read the rs crate changelog for CreateResponseArgs breaking changes before upgrading.
When it happens
Trigger: Calling search/search_with_titles with a model the builder deems invalid, or argument combinations the rs crate's CreateResponseArgs rejects (e.g. invalid max_output_tokens, mutually inconsistent fields, or a crate version where a previously optional field is now required).
Common situations: Configured model name is empty or unsupported after an API update; upgrading the rs crate changed builder invariants; programmatic callers overriding model with a bad value from config/env.
Related errors
- Failed to build web search tool: {e}
- invalid worktree id from dest: {worktree_id}
- invalid worktree id {:?}
- invalid {GROK_CHAT_LOCAL_WORKSPACE_MODE_ENV}={other:?}; expe
- Error: --session-id must be a valid UUID (got '{session_id}'
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/537d6f09c06a4067.
Report an issue: GitHub.