{"record":{"id":"12b310fb48c097bb","repo":"BoundaryML/baml","slug":"http-body-is-not-json","errorCode":null,"errorMessage":"HTTP body is not JSON: {}","messagePattern":"HTTP body is not JSON: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"engine/baml-lib/baml-types/src/tracing/events.rs","lineNumber":295,"sourceCode":"    }\n}\n\nimpl HTTPBody {\n    pub fn new(body: Vec<u8>) -> Self {\n        Self { raw: body }\n    }\n\n    pub fn raw(&self) -> &[u8] {\n        &self.raw\n    }\n\n    pub fn text(&self) -> anyhow::Result<&str> {\n        std::str::from_utf8(&self.raw).map_err(|e| anyhow::anyhow!(\"HTTP body is not UTF-8: {}\", e))\n    }\n\n    pub fn json(&self) -> anyhow::Result<serde_json::Value> {\n        serde_json::from_str(self.text()?)\n            .map_err(|e| anyhow::anyhow!(\"HTTP body is not JSON: {}\", e))\n    }\n\n    /// Returns the HTTP body as a [`serde_json::Value`].\n    ///\n    /// If the body is not UTF-8 or JSON, it is returned as an array of bytes.\n    /// Used as input for [`serde_json::to_string_pretty`].\n    pub fn as_serde_value(&self) -> serde_json::Value {\n        self.json()\n            .or_else(|_e| self.text().map(|s| serde_json::Value::String(s.into())))\n            .unwrap_or_else(|_e| {\n                serde_json::Value::Array(\n                    self.raw()\n                        .iter()\n                        .map(|byte| serde_json::Value::from(*byte))\n                        .collect(),\n                )\n            })\n    }","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-lib/baml-types/src/tracing/events.rs#L277-L313","documentation":"HttpBody::json first requires the body to be UTF-8 (via text()) and then parses it as JSON with serde_json. Either failure surfaces as \"HTTP body is not JSON: {e}\". It means the recorded HTTP body was not a JSON document.","triggerScenarios":"Calling HttpBody::json() on bodies that are HTML error pages, plain-text messages, empty bodies, or truncated/invalid JSON from an upstream provider.","commonSituations":"Provider outages returning HTML 502 pages; streaming/SSE payloads inspected as one JSON document; endpoints returning form-encoded or plain-text responses.","solutions":["Check the HTTP status and Content-Type header; only parse JSON when Content-Type is application/json.","Inspect body.text() first and handle empty/HTML bodies before calling json().","Handle streaming (SSE) bodies line-by-line rather than as a single JSON value.","Fall back to raw()/as_serde_value byte-array representation when JSON parsing is not required."],"exampleFix":"// before\nlet v = body.json()?;\n// after\nlet v = match body.json() {\n    Ok(v) => v,\n    Err(e) => { log::warn!(\"non-JSON body: {}\", body.text().unwrap_or(\"<binary>\")); serde_json::Value::Null }\n};","handlingStrategy":"type-guard","validationCode":"let parseable = std::str::from_utf8(body.raw()).map(|s| serde_json::from_str::<serde_json::Value>(s).is_ok()).unwrap_or(false);","typeGuard":"fn is_json_body(b: &HttpBody) -> bool { b.text().map(|t| serde_json::from_str::<serde_json::Value>(t).is_ok()).unwrap_or(false) }","tryCatchPattern":"let v = body.json().unwrap_or(serde_json::Value::Null);","preventionTips":["Verify Content-Type is application/json before parsing","Inspect status codes — error pages are usually HTML","Treat SSE/streaming bodies separately from single JSON documents"],"tags":["http","json","parsing"],"backgroundTag":"json-parse-error","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}