{"record":{"id":"8152b0393803d99b","repo":"xai-org/grok-build","slug":"invalid-acp-content-blocks-in-content-e","errorCode":null,"errorMessage":"Invalid ACP content blocks in \"content\": {e}","messagePattern":"Invalid ACP content blocks in \"content\": (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-pager/src/headless/cli.rs","lineNumber":114,"sourceCode":"\n    let blocks: Vec<acp::ContentBlock> = match value {\n        serde_json::Value::Array(_) => serde_json::from_value(value)\n            .map_err(|e| anyhow::anyhow!(\"Invalid ACP content blocks: {e}\"))?,\n\n        serde_json::Value::Object(ref map) => {\n            let format_type = map.get(\"type\").and_then(|v| v.as_str()).ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"JSON object must have a \\\"type\\\" field \\\n                         (e.g., {{\\\"type\\\": \\\"acp\\\", \\\"content\\\": [...]}})\"\n                )\n            })?;\n            let content = map\n                .get(\"content\")\n                .ok_or_else(|| anyhow::anyhow!(\"JSON object must have a \\\"content\\\" field\"))?;\n\n            match format_type {\n                \"acp\" => serde_json::from_value(content.clone()).map_err(|e| {\n                    anyhow::anyhow!(\"Invalid ACP content blocks in \\\"content\\\": {e}\")\n                })?,\n                other => anyhow::bail!(\n                    \"Unsupported prompt format type: \\\"{other}\\\". Supported types: \\\"acp\\\"\"\n                ),\n            }\n        }\n\n        _ => {\n            anyhow::bail!(\"Expected JSON array or {{\\\"type\\\": \\\"...\\\", \\\"content\\\": [...]}} object\")\n        }\n    };\n\n    if blocks.is_empty() {\n        anyhow::bail!(\"content blocks array is empty\");\n    }\n    Ok(blocks)\n}\n","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-pager/src/headless/cli.rs#L96-L132","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n{\"type\":\"acp\",\"content\":{\"type\":\"text\",\"text\":\"hi\"}}\n// after\n{\"type\":\"acp\",\"content\":[{\"type\":\"text\",\"text\":\"hi\"}]}","handlingStrategy":"validation","validationCode":"fn content_blocks_ok(s: &str) -> bool {\n    serde_json::from_str::<serde_json::Value>(s)\n        .ok()\n        .and_then(|v| v.get(\"content\").cloned())\n        .map(|c| serde_json::from_value::<Vec<xai_grok_shell::acp::ContentBlock>>(c).is_ok())\n        .unwrap_or(false)\n}","typeGuard":"fn is_block_array(v: &serde_json::Value) -> bool {\n    v.as_array()\n        .map(|a| !a.is_empty() || true)\n        .unwrap_or(false)\n}\n// array-ness is cheap; full schema check requires from_value::<Vec<acp::ContentBlock>>","tryCatchPattern":"match HeadlessPrompt::from_json(&raw) {\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"Invalid ACP content blocks in \\\"content\\\"\") => {\n        eprintln!(\"fix the block at the index serde reports: {e}\");\n        std::process::exit(2);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["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."],"tags":["json","schema","acp","serde"],"backgroundTag":"schema-validation-failed","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}