xai-org/grok-build · error

Invalid ACP content blocks: {e}

Error message

Invalid ACP content blocks: {e}

What it means

When parse_prompt_json receives a JSON array ([...]), it deserializes the whole value into Vec<acp::ContentBlock>. If the array is valid JSON but its elements do not match the ContentBlock schema, the serde error is wrapped as "Invalid ACP content blocks: {e}". This separates shape validation failures from raw JSON syntax failures.

Source

Thrown at crates/codegen/xai-grok-pager/src/headless/cli.rs:99

        Ok(Self::Blocks(blocks))
    }

    pub fn into_content_blocks(self) -> Vec<acp::ContentBlock> {
        match self {
            Self::Text(text) => vec![acp::ContentBlock::Text(acp::TextContent::new(text))],
            Self::Blocks(blocks) => blocks,
        }
    }
}

/// Parse ACP content blocks from an array (`[...]`) or typed wrapper (`{"type":"acp","content":[...]}`).
fn parse_prompt_json(json_str: &str) -> anyhow::Result<Vec<acp::ContentBlock>> {
    let value: serde_json::Value =
        serde_json::from_str(json_str).map_err(|e| anyhow::anyhow!("Invalid JSON: {e}"))?;

    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\""

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Read the serde message after the prefix for the exact index and missing/unknown field.
  2. Ensure every array element is a valid acp::ContentBlock (known "type" plus its required fields).
  3. If the payload is a single block, either wrap it in an array or use the {"type":"acp","content":[...]} wrapper object form.
  4. Validate the payload against the ContentBlock schema before calling from_json.

Example fix

// before
[{"type":"txt","text":"hi"}]
// after
[{"type":"text","text":"hi"}]
Defensive patterns

Strategy: validation

Validate before calling

fn blocks_array_ok(s: &str) -> bool {
    serde_json::from_str::<Vec<xai_grok_shell::acp::ContentBlock>>(s).is_ok()
}
// pre-check before from_json when the payload is a top-level array

Type guard

fn as_acp_blocks(v: &serde_json::Value) -> Option<&Vec<serde_json::Value>> {
    v.as_array()
}
// then round-trip each element through serde_json::from_value::<acp::ContentBlock> to confirm the schema

Try / catch

match HeadlessPrompt::from_json(&raw) {
    Ok(p) => p,
    Err(e) if e.to_string().contains("Invalid ACP content blocks") => {
        eprintln!("each array element must be a valid ContentBlock: {e}");
        std::process::exit(2);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Passing a top-level JSON array whose elements lack required ContentBlock fields, use an unknown "type" value, or have fields with wrong types (e.g. text as a number) — any serde_json::from_value failure on the array form.

Common situations: Mistyping a block type name; omitting the required "text" (or other) field of a content block; mixing a legacy/different schema version's block format into the current CLI.

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


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