{"record":{"id":"d06e869e15706051","repo":"xai-org/grok-build","slug":"prompt-json-e","errorCode":null,"errorMessage":"--prompt-json: {e}","messagePattern":"--prompt-json: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-pager/src/headless/cli.rs","lineNumber":50,"sourceCode":"    Text(String),\n    Blocks(Vec<acp::ContentBlock>),\n}\n\nimpl HeadlessPrompt {\n    /// Build from mutually-exclusive CLI prompt args. `None` means interactive mode.\n    pub fn from_args(\n        single: Option<&str>,\n        prompt_json: Option<&str>,\n        prompt_file: Option<&Path>,\n    ) -> anyhow::Result<Option<Self>> {\n        if let Some(text) = single {\n            Self::from_text(text)\n                .map(Some)\n                .map_err(|e| anyhow::anyhow!(\"--single: {e}\"))\n        } else if let Some(json_str) = prompt_json {\n            Self::from_json(json_str)\n                .map(Some)\n                .map_err(|e| anyhow::anyhow!(\"--prompt-json: {e}\"))\n        } else if let Some(path) = prompt_file {\n            Self::from_file(path).map(Some)\n        } else {\n            Ok(None)\n        }\n    }\n\n    /// `.json` files are parsed as content blocks, everything else as text.\n    pub fn from_file(path: &Path) -> anyhow::Result<Self> {\n        let content = std::fs::read_to_string(path)\n            .map_err(|e| anyhow::anyhow!(\"Failed to read '{}': {e}\", path.display()))?;\n\n        let context = |e| anyhow::anyhow!(\"'{}': {e}\", path.display());\n        if path.extension().and_then(|e| e.to_str()) == Some(\"json\") {\n            Self::from_json(&content).map_err(context)\n        } else {\n            Self::from_text(&content).map_err(context)\n        }","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-pager/src/headless/cli.rs#L32-L68","documentation":"PromptSource::from_args wraps failures of Self::from_json(json_str) as '--prompt-json: {e}'. The --prompt-json flag value must parse as the expected prompt content-blocks JSON; invalid JSON or a structure that does not match the content-block schema produces this error.","triggerScenarios":"Passing --prompt-json with malformed JSON, or JSON whose shape is not valid prompt content blocks (wrong array/object shape, unknown block types, missing required fields).","commonSituations":"Hand-writing content-block JSON with syntax errors; copying block format from a different API version; jq/yq output piped with quoting issues.","solutions":["Validate the JSON structure against the content-block schema before passing","Pipe through jq '.' to catch syntax errors early","Use --prompt-file with a .json file instead of an inline flag","Check the inner {e} for the exact deserialization field mismatch"],"exampleFix":"// before\n--prompt-json '[{\"type\": \"text\"}]'\n// after\n--prompt-json '[{\"type\": \"text\", \"text\": \"hello\"}]'","handlingStrategy":"validation","validationCode":"fn validate_prompt_json(s: &str) -> Result<(), String> {\n    let v: serde_json::Value = serde_json::from_str(s)\n        .map_err(|e| format!(\"invalid JSON: {e}\"))?;\n    let blocks = v.as_array().ok_or(\"expected array of content blocks\")?;\n    for b in blocks {\n        if b.get(\"type\").and_then(|t| t.as_str()).is_none() {\n            return Err(\"block missing 'type'\".into());\n        }\n    }\n    Ok(())\n}","typeGuard":"fn is_content_block_array(s: &str) -> bool {\n    serde_json::from_str::<serde_json::Value>(s).ok()\n        .and_then(|v| v.as_array().map(|a| {\n            !a.is_empty() && a.iter().all(|b| b.get(\"type\").and_then(|t| t.as_str()).is_some())\n        }))\n        .unwrap_or(false)\n}","tryCatchPattern":"match PromptSource::from_args(None, prompt_json.as_deref(), None) {\n    Ok(Some(src)) => src,\n    Ok(None) => { eprintln!(\"no prompt given\"); std::process::exit(2); }\n    Err(e) => { eprintln!(\"{e:#}\"); std::process::exit(2); }\n}","preventionTips":["Validate content-block JSON against the schema before passing","Generate blocks with a typed builder, not string concatenation","Pipe through jq '.' to catch syntax errors","Pin the content-block schema version used by your tooling"],"tags":["cli","json","prompt","deserialization"],"backgroundTag":"invalid-json-input","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}