xai-org/grok-build · error
JSON object must have a "type" field (e.g., {"type": "acp",
Error message
JSON object must have a "type" field (e.g., {"type": "acp", "content": [...]}) What it means
When the prompt JSON is an object, parse_prompt_json requires a string "type" field to select the format. If the object has no "type" key or it is not a string, this bail message is returned verbatim, including the expected wrapper example. It exists to guide users to the typed wrapper format {"type":"acp","content":[...]}.
Source
Thrown at crates/codegen/xai-grok-pager/src/headless/cli.rs:103
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
- Add a string "type" field with value "acp" to the wrapper object.
- Or pass the blocks as a top-level JSON array instead of an object.
- Quote the type value: JSON requires "type":"acp", not type:acp.
- Confirm the top-level object is the prompt wrapper, not the content block itself (a block object should be inside the content array).
Example fix
// before
{"content":[{"type":"text","text":"hi"}]}
// after
{"type":"acp","content":[{"type":"text","text":"hi"}]} Defensive patterns
Strategy: validation
Validate before calling
fn wrapper_has_type(s: &str) -> bool {
serde_json::from_str::<serde_json::Value>(s)
.ok()
.and_then(|v| v.get("type").and_then(|t| t.as_str()).map(|_| true))
.unwrap_or(false)
} Type guard
fn is_acp_wrapper(v: &serde_json::Value) -> bool {
v.as_object()
.and_then(|o| o.get("type").and_then(|t| t.as_str()))
.map(|t| t == "acp")
.unwrap_or(false)
} Try / catch
match HeadlessPrompt::from_json(&raw) {
Ok(p) => p,
Err(e) if e.to_string().contains("must have a \"type\" field") => {
eprintln!("wrap the object as {\"type\":\"acp\",\"content\":[...]}");
std::process::exit(2);
}
Err(e) => return Err(e),
} Prevention
- Always include "type":"acp" when using the object wrapper form.
- Prefer the plain array form when you don't need a wrapper.
- Quote all JSON keys and string values in hand-written payloads.
- Add a shape check ({type,content}) to any script generating prompts.
When it happens
Trigger: Calling from_json with a JSON object like {"content":[...]}, {"prompt":"..."}, or {"type":123} — i.e. an object whose "type" key is absent or non-string.
Common situations: Wrapping blocks in an object but forgetting the discriminator; passing a plain config-like object as a prompt; older tooling emitting a wrapper without the "type" key.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- JSON object must have a "content" field
- Failed to load manifest: {e}
- --json-schema: invalid JSON: {e}
- --prompt-json: {e}
- Invalid JSON: {e}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/adf751b59f453db5.
Report an issue: GitHub.