{"record":{"id":"9efb66ac6e816904","repo":"wavetermdev/waveterm","slug":"invalid-request-body-v","errorCode":null,"errorMessage":"Invalid request body: %v","messagePattern":"Invalid request body: (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"pkg/aiusechat/usechat.go","lineNumber":645,"sourceCode":"\tBuilderId    string            `json:\"builderid,omitempty\"`\n\tBuilderAppId string            `json:\"builderappid,omitempty\"`\n\tChatID       string            `json:\"chatid\"`\n\tMsg          uctypes.AIMessage `json:\"msg\"`\n\tWidgetAccess bool              `json:\"widgetaccess,omitempty\"`\n\tAIMode       string            `json:\"aimode\"`\n}\n\nfunc WaveAIPostMessageHandler(w http.ResponseWriter, r *http.Request) {\n\t// Only allow POST method\n\tif r.Method != http.MethodPost {\n\t\thttp.Error(w, \"Method not allowed\", http.StatusMethodNotAllowed)\n\t\treturn\n\t}\n\n\t// Parse request body\n\tvar req PostMessageRequest\n\tif err := json.NewDecoder(r.Body).Decode(&req); err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"Invalid request body: %v\", err), http.StatusBadRequest)\n\t\treturn\n\t}\n\n\t// Validate chatid is present and is a UUID\n\tif req.ChatID == \"\" {\n\t\thttp.Error(w, \"chatid is required in request body\", http.StatusBadRequest)\n\t\treturn\n\t}\n\tif _, err := uuid.Parse(req.ChatID); err != nil {\n\t\thttp.Error(w, \"chatid must be a valid UUID\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\t// Get RTInfo from TabId or BuilderId\n\tvar rtInfo *waveobj.ObjRTInfo\n\tif req.TabId != \"\" {\n\t\toref := waveobj.MakeORef(waveobj.OType_Tab, req.TabId)\n\t\trtInfo = wstore.GetRTInfo(oref)","sourceCodeStart":627,"sourceCodeEnd":663,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/usechat.go#L627-L663","documentation":"The handler failed to JSON-decode the POST request body into PostMessageRequest and returns 400 with the decode error embedded. Causes are malformed JSON, wrong Content-Type handling, empty body, or body fields of the wrong type (e.g. arrays where objects are expected).","triggerScenarios":"POSTing to the WaveAIPostMessageHandler route with a body that is not valid JSON (trailing commas, HTML error page from a proxy, empty payload), or with fields whose JSON types don't match PostMessageRequest (chatid/message must be strings, not numbers/objects).","commonSituations":"Forgetting to set Content-Type and sending form-encoded data; double-encoding the payload as a string; a load balancer returning an HTML 502 page that gets forwarded as the body; omitting the body entirely in a curl -X POST.","solutions":["Send valid JSON with Content-Type: application/json and an object matching PostMessageRequest: {\"chatid\": \"...\", \"message\": \"...\"}.","Inspect the %v detail in the 400 response — it names the exact JSON decode problem (unexpected end of JSON input, cannot unmarshal number into string, etc.).","Check for proxies/middleware mangling the body (HTML error pages, chunked encoding issues) and ensure the raw body reaches the handler."],"exampleFix":"// before\ncurl -X POST /api/aiusechat/message # empty body -> 400\n// after\ncurl -X POST /api/aiusechat/message \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"chatid\":\"<uuid>\",\"message\":\"hello\"}'","handlingStrategy":"validation","validationCode":"const body = { chatid: chatId, message: text, aimode: mode };\nif (typeof chatid !== 'string' || chatid.length === 0) throw new Error('chatid required');\nJSON.stringify(body); // throws early on non-serializable values","typeGuard":"function isPostMessageRequest(b) {\n    return typeof b === 'object' && b !== null &&\n        typeof b.chatid === 'string' && b.chatid.length > 0 &&\n        typeof b.message === 'string';\n}","tryCatchPattern":"const res = await fetch(url, { method: \"POST\", headers: {\"Content-Type\": \"application/json\"}, body: JSON.stringify(payload) });\nif (res.status === 400) {\n    const text = await res.text();\n    throw new Error(`request rejected: ${text}`); // includes JSON decode detail\n}","preventionTips":["Always send a valid JSON object body with Content-Type: application/json","Match field types to PostMessageRequest (strings, not numbers/objects)","Handle the server's 400 body — it echoes the exact json.Decode error","Verify no proxy rewrites the body (e.g. HTML error pages)"],"tags":["http","json","bad-request","api"],"backgroundTag":"invalid-json-request-body","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}