xai-org/grok-build · error

Invalid JSON: {e}

Error message

Invalid JSON: {e}

What it means

parse_prompt_json first runs serde_json::from_str on the raw prompt string before interpreting it as ACP content blocks. If the string is not syntactically valid JSON at all, the serde error is wrapped as "Invalid JSON: {e}". This library throws it so users of the headless CLI get a clear, early failure that the prompt argument itself is malformed, distinct from later semantic/validation errors.

Source

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

    }

    fn from_json(json_str: &str) -> anyhow::Result<Self> {
        let blocks = parse_prompt_json(json_str)?;
        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| {

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Run the prompt string through a JSON linter/parser (e.g. jq . or JSON.parse) to find the syntax error reported by serde.
  2. If building JSON in a script, serialize it programmatically (serde_json::json!, jq -n, JSON.stringify) instead of string concatenation.
  3. If the payload is a plain text prompt, pass it as a JSON string or use the non-JSON prompt form instead of from_json.
  4. Check the serde message after 'Invalid JSON:' for the exact line/column of the syntax fault.

Example fix

// before
let prompt = format!("{{\"type\":\"acp\",\"content\":{user_text}}}");
// after
let prompt = serde_json::json!({"type":"acp","content":[{"type":"text","text":user_text}]}).to_string();
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_json(s: &str) -> bool {
    serde_json::from_str::<serde_json::Value>(s).is_ok()
}
// only call HeadlessPrompt::from_json if is_valid_json(prompt)

Try / catch

// Rust: match on the Result and handle the invalid-JSON branch explicitly
match HeadlessPrompt::from_json(&raw) {
    Ok(p) => p,
    Err(e) if e.to_string().starts_with("Invalid JSON:") => {
        eprintln!("prompt is not valid JSON: {e}");
        std::process::exit(2);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling HeadlessPrompt::from_json (or the CLI prompt parsing path) with a string that serde_json::from_str rejects: unquoted keys, single quotes, trailing commas, unescaped newlines/control characters, truncated output, or a non-JSON plain-text prompt passed where JSON was expected.

Common situations: Hand-writing prompt JSON in a shell where quotes get eaten; pasting JSON that was pretty-printed with comments; a script interpolating unescaped user text into the JSON string; passing a file path or plain text instead of JSON contents.

Understand the failure class

Related errors


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