wavetermdev/waveterm · warning
Invalid request body: %v
Error message
Invalid request body: %v
What it means
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).
Source
Thrown at pkg/aiusechat/usechat.go:645
BuilderId string `json:"builderid,omitempty"`
BuilderAppId string `json:"builderappid,omitempty"`
ChatID string `json:"chatid"`
Msg uctypes.AIMessage `json:"msg"`
WidgetAccess bool `json:"widgetaccess,omitempty"`
AIMode string `json:"aimode"`
}
func WaveAIPostMessageHandler(w http.ResponseWriter, r *http.Request) {
// Only allow POST method
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// Parse request body
var req PostMessageRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, fmt.Sprintf("Invalid request body: %v", err), http.StatusBadRequest)
return
}
// Validate chatid is present and is a UUID
if req.ChatID == "" {
http.Error(w, "chatid is required in request body", http.StatusBadRequest)
return
}
if _, err := uuid.Parse(req.ChatID); err != nil {
http.Error(w, "chatid must be a valid UUID", http.StatusBadRequest)
return
}
// Get RTInfo from TabId or BuilderId
var rtInfo *waveobj.ObjRTInfo
if req.TabId != "" {
oref := waveobj.MakeORef(waveobj.OType_Tab, req.TabId)
rtInfo = wstore.GetRTInfo(oref)View on GitHub (pinned to a4447c1563)
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.
Example fix
// before
curl -X POST /api/aiusechat/message # empty body -> 400
// after
curl -X POST /api/aiusechat/message \
-H 'Content-Type: application/json' \
-d '{"chatid":"<uuid>","message":"hello"}' Defensive patterns
Strategy: validation
Validate before calling
const body = { chatid: chatId, message: text, aimode: mode };
if (typeof chatid !== 'string' || chatid.length === 0) throw new Error('chatid required');
JSON.stringify(body); // throws early on non-serializable values Type guard
function isPostMessageRequest(b) {
return typeof b === 'object' && b !== null &&
typeof b.chatid === 'string' && b.chatid.length > 0 &&
typeof b.message === 'string';
} Try / catch
const res = await fetch(url, { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(payload) });
if (res.status === 400) {
const text = await res.text();
throw new Error(`request rejected: ${text}`); // includes JSON decode detail
} Prevention
- 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)
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- failed to decode tsunami response: %w
- Method not allowed
- Invalid VDOM URL format
- failed to parse JSON: %v
- missing zone file info for ${zoneId}:${fileName}
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/9efb66ac6e816904.
Report an issue: GitHub.