xai-org/grok-build · error

--json-schema: invalid JSON: {e}

Error message

--json-schema: invalid JSON: {e}

What it means

parse_json_schema parses the --json-schema flag value with serde_json::from_str and wraps parse failures as '--json-schema: invalid JSON: {e}'. A following check also rejects non-object schemas. It exists so malformed structured-output schemas fail fast at argument parsing.

Source

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

use agent_client_protocol as acp;
use clap::ValueEnum;

#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, ValueEnum)]
pub enum OutputFormat {
    #[default]
    Plain,
    Json,
    /// NDJSON: one ACP session update per line, the agent's native format.
    #[value(name = "streaming-json")]
    StreamingJson,
    /// NDJSON in the Anthropic Messages API wire format.
    #[value(name = "streaming-messages-json")]
    StreamingMessagesJson,
}

pub fn parse_json_schema(input: &str) -> anyhow::Result<serde_json::Value> {
    let schema: serde_json::Value = serde_json::from_str(input)
        .map_err(|e| anyhow::anyhow!("--json-schema: invalid JSON: {e}"))?;
    if !schema.is_object() {
        anyhow::bail!("--json-schema: must be a JSON object describing a JSON Schema");
    }
    Ok(schema)
}

#[derive(Debug, Clone)]
pub enum HeadlessPrompt {
    Text(String),
    Blocks(Vec<acp::ContentBlock>),
}

impl HeadlessPrompt {
    /// Build from mutually-exclusive CLI prompt args. `None` means interactive mode.
    pub fn from_args(
        single: Option<&str>,
        prompt_json: Option<&str>,
        prompt_file: Option<&Path>,

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Validate the JSON with jq/python before passing it
  2. Use single-quoted heredocs or --@file-style input to avoid shell mangling
  3. Ensure the top level is a JSON object
  4. Prefer reading the schema from a file rather than an inline flag

Example fix

// before
--json-schema '{"type": "object", properties: {}}'
// after
--json-schema '{"type": "object", "properties": {}}'
Defensive patterns

Strategy: validation

Validate before calling

fn validate_schema_arg(input: &str) -> Result<(), String> {
    let v: serde_json::Value = serde_json::from_str(input)
        .map_err(|e| format!("--json-schema: invalid JSON: {e}"))?;
    if !v.is_object() { return Err("--json-schema: must be a JSON object".into()); }
    Ok(())
}

Type guard

fn is_json_object(s: &str) -> bool {
    serde_json::from_str::<serde_json::Value>(s)
        .map(|v| v.is_object())
        .unwrap_or(false)
}

Try / catch

match parse_json_schema(raw) {
    Ok(schema) => schema,
    Err(e) => { eprintln!("{e:#}"); std::process::exit(2); }
}

Prevention

When it happens

Trigger: Passing --json-schema with malformed JSON (trailing commas, single quotes, unquoted keys) or with a valid JSON value that is not an object (e.g. a bare string or array).

Common situations: Building the flag with shell quoting that mangles the JSON; generating the schema with string concatenation; YAML or JS-object-literal syntax pasted in instead of strict JSON.

Understand the failure class

Related errors


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