xai-org/grok-build · error
Invalid ACP content blocks in "content": {e}
Error message
Invalid ACP content blocks in "content": {e} What it means
For the {"type":"acp","content":[...]} wrapper form, the "content" value is deserialized into Vec<acp::ContentBlock> via serde_json::from_value. If the content array's elements violate the ContentBlock schema, the serde error is wrapped as "Invalid ACP content blocks in \"content\": {e}". This localizes the failure to the content field specifically.
Source
Thrown at crates/codegen/xai-grok-pager/src/headless/cli.rs:114
let blocks: Vec<acp::ContentBlock> = match value {
serde_json::Value::Array(_) => serde_json::from_value(value)
.map_err(|e| anyhow::anyhow!("Invalid ACP content blocks: {e}"))?,
serde_json::Value::Object(ref map) => {
let format_type = map.get("type").and_then(|v| v.as_str()).ok_or_else(|| {
anyhow::anyhow!(
"JSON object must have a \"type\" field \
(e.g., {{\"type\": \"acp\", \"content\": [...]}})"
)
})?;
let content = map
.get("content")
.ok_or_else(|| anyhow::anyhow!("JSON object must have a \"content\" field"))?;
match format_type {
"acp" => serde_json::from_value(content.clone()).map_err(|e| {
anyhow::anyhow!("Invalid ACP content blocks in \"content\": {e}")
})?,
other => anyhow::bail!(
"Unsupported prompt format type: \"{other}\". Supported types: \"acp\""
),
}
}
_ => {
anyhow::bail!("Expected JSON array or {{\"type\": \"...\", \"content\": [...]}} object")
}
};
if blocks.is_empty() {
anyhow::bail!("content blocks array is empty");
}
Ok(blocks)
}
View on GitHub (pinned to bc7f02eddd)
Solutions
- Read the serde detail for the failing index/field and fix that block.
- Ensure "content" is an array, wrapping a single block in [ ... ].
- Match each block exactly to acp::ContentBlock variants (valid "type" plus required fields).
- Generate the payload with serde_json::json! or from a known-good example to guarantee the schema.
Example fix
// before
{"type":"acp","content":{"type":"text","text":"hi"}}
// after
{"type":"acp","content":[{"type":"text","text":"hi"}]} Defensive patterns
Strategy: validation
Validate before calling
fn content_blocks_ok(s: &str) -> bool {
serde_json::from_str::<serde_json::Value>(s)
.ok()
.and_then(|v| v.get("content").cloned())
.map(|c| serde_json::from_value::<Vec<xai_grok_shell::acp::ContentBlock>>(c).is_ok())
.unwrap_or(false)
} Type guard
fn is_block_array(v: &serde_json::Value) -> bool {
v.as_array()
.map(|a| !a.is_empty() || true)
.unwrap_or(false)
}
// array-ness is cheap; full schema check requires from_value::<Vec<acp::ContentBlock>> Try / catch
match HeadlessPrompt::from_json(&raw) {
Ok(p) => p,
Err(e) if e.to_string().contains("Invalid ACP content blocks in \"content\"") => {
eprintln!("fix the block at the index serde reports: {e}");
std::process::exit(2);
}
Err(e) => return Err(e),
} Prevention
- Wrap single blocks in an array: "content":[{...}], never "content":{...}.
- Reuse the same serializer that produced working payloads for prior prompts.
- Test generated wrappers with serde round-trips in unit tests.
- Keep block schemas in sync with the acp crate version you compile against.
When it happens
Trigger: Wrapper object has type:"acp" and a "content" key, but the content value is not an array of valid ContentBlocks: unknown block "type", missing required fields, wrong field types, or content being a single object/string instead of an array.
Common situations: Putting one block object directly in "content" instead of an array; using block types from a different ACP version; nested image/tool blocks with mismatched field names.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Invalid ACP content blocks: {e}
- response parse error: {e}
- Invalid JSON: {e}
- JSON object must have a "type" field (e.g., {"type": "acp",
- JSON object must have a "content" field
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/8152b0393803d99b.
Report an issue: GitHub.