{"record":{"id":"c443bbf0e662eb5a","repo":"sigoden/aichat","slug":"invalid-request-json-err","errorCode":null,"errorMessage":"Invalid request json, {err}","messagePattern":"Invalid request json, (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/serve.rs","lineNumber":239,"sourceCode":"        let data = json!({ \"data\": self.roles });\n        let res = Response::builder()\n            .header(\"Content-Type\", \"application/json; charset=utf-8\")\n            .body(Full::new(Bytes::from(data.to_string())).boxed())?;\n        Ok(res)\n    }\n\n    fn list_rags(&self) -> Result<AppResponse> {\n        let data = json!({ \"data\": self.rags });\n        let res = Response::builder()\n            .header(\"Content-Type\", \"application/json; charset=utf-8\")\n            .body(Full::new(Bytes::from(data.to_string())).boxed())?;\n        Ok(res)\n    }\n\n    async fn search_rag(&self, req: hyper::Request<Incoming>) -> Result<AppResponse> {\n        let req_body = req.collect().await?.to_bytes();\n        let req_body: Value = serde_json::from_slice(&req_body)\n            .map_err(|err| anyhow!(\"Invalid request json, {err}\"))?;\n\n        debug!(\"search rag request: {req_body}\");\n        let SearchRagReqBody { name, input } = serde_json::from_value(req_body)\n            .map_err(|err| anyhow!(\"Invalid request body, {err}\"))?;\n\n        let config = Arc::new(RwLock::new(self.config.clone()));\n\n        let abort_signal = create_abort_signal();\n\n        let rag_path = config.read().rag_file(&name);\n        let rag = Rag::load(&config, &name, &rag_path)?;\n\n        let rag_result = Config::search_rag(&config, &rag, &input, abort_signal).await?;\n\n        let data = json!({ \"data\": rag_result });\n        let res = Response::builder()\n            .header(\"Content-Type\", \"application/json; charset=utf-8\")\n            .body(Full::new(Bytes::from(data.to_string())).boxed())?;","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/sigoden/aichat/blob/82976d349ad97ac9aae0655ad631dace5e2a6385/src/serve.rs#L221-L257","documentation":"The /search-rag handler reads the request body and deserializes it as JSON; malformed JSON fails with this error (a second, distinct error covers valid JSON with wrong fields). The raw serde error is interpolated for diagnosis.","triggerScenarios":"POSTing to search_rag with a body that is not valid JSON: empty body, HTML/plain text, truncated JSON, or wrong Content-Type payload.","commonSituations":"Forgetting to send a body; curl without proper quoting; clients sending form-encoded data; proxies truncating large bodies.","solutions":["Send a valid JSON body with Content-Type: application/json","Validate the payload with a JSON linter before sending","Ensure the body isn't empty or truncated in transit"],"exampleFix":"// before\ncurl -X POST localhost:8000/search-rag -d name=docs\n// after\ncurl -X POST localhost:8000/search-rag -H 'Content-Type: application/json' -d '{\"name\":\"docs\",\"input\":\"query\"}'","handlingStrategy":"validation","validationCode":"fn valid_search_body(s: &str) -> bool {\n    serde_json::from_str::<serde_json::Value>(s)\n        .ok()\n        .map(|v| v.get(\"name\").is_some() && v.get(\"input\").is_some())\n        .unwrap_or(false)\n}","typeGuard":"fn as_search_body(b: &[u8]) -> Option<(String, String)> {\n    let v: serde_json::Value = serde_json::from_slice(b).ok()?;\n    Some((v.get(\"name\")?.as_str()?.into(), v.get(\"input\")?.as_str()?.into()))\n}","tryCatchPattern":"let res = client.post(url).json(&json!({\"name\": rag, \"input\": q})).send().await?;\nif res.status().is_client_error() {\n    let msg = res.text().await?;\n    eprintln!(\"Bad request: {msg}\");\n}","preventionTips":["Always send Content-Type: application/json with a JSON body","Validate payloads client-side before POSTing","Never send empty bodies to /search-rag"],"tags":["http","json","request-validation"],"backgroundTag":"json-parse-error","analyzedSha":"82976d349ad97ac9aae0655ad631dace5e2a6385","analyzedAt":"2026-09-09T18:33:06.139Z","contentChangedAt":"2026-09-09T18:33:06.139Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}