{"record":{"id":"ed58e8b1ac58471e","repo":"SigNoz/signoz","slug":"invalid-request-body-v","errorCode":null,"errorMessage":"invalid request body: %v","messagePattern":"invalid request body: (.+?)","errorType":"http","errorClass":"model.ApiError","httpStatus":400,"severity":"error","filePath":"pkg/query-service/app/http_handler.go","lineNumber":4379,"sourceCode":"\tvars := mux.Vars(r)\n\tfunnelID := vars[\"funnel_id\"]\n\n\tclaims, err := authtypes.ClaimsFromContext(r.Context())\n\n\tif err != nil {\n\t\trender.Error(w, err)\n\t\treturn\n\t}\n\n\tfunnel, err := aH.Signoz.Modules.TraceFunnel.Get(r.Context(), valuer.MustNewUUID(funnelID), valuer.MustNewUUID(claims.OrgID))\n\tif err != nil {\n\t\tRespondError(w, &model.ApiError{Typ: model.ErrorNotFound, Err: fmt.Errorf(\"funnel not found: %v\", err)}, nil)\n\t\treturn\n\t}\n\n\tvar req traceFunnels.StepTransitionRequest\n\tif err := json.NewDecoder(r.Body).Decode(&req); err != nil {\n\t\tRespondError(w, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf(\"invalid request body: %v\", err)}, nil)\n\t\treturn\n\t}\n\n\tchq, err := traceFunnelsModule.GetSlowestTraces(funnel, req.TimeRange, req.StepStart, req.StepEnd)\n\tif err != nil {\n\t\tRespondError(w, &model.ApiError{Typ: model.ErrorInternal, Err: fmt.Errorf(\"error building clickhouse query: %v\", err)}, nil)\n\t\treturn\n\t}\n\n\tresults, err := aH.reader.GetListResultV3(r.Context(), chq.Query)\n\tif err != nil {\n\t\tRespondError(w, &model.ApiError{Typ: model.ErrorInternal, Err: fmt.Errorf(\"error converting clickhouse results to list: %v\", err)}, nil)\n\t\treturn\n\t}\n\taH.Respond(w, results)\n}\n\nfunc (aH *APIHandler) handleFunnelErrorTraces(w http.ResponseWriter, r *http.Request) {","sourceCodeStart":4361,"sourceCodeEnd":4397,"githubUrl":"https://github.com/SigNoz/signoz/blob/5069bf80b08f1f00d7e014eccc09902f9871004f/pkg/query-service/app/http_handler.go#L4361-L4397","documentation":"Thrown while decoding the JSON body of the slow-traces funnel endpoint into traceFunnels.StepTransitionRequest. The handler for GET/POST funnel slow traces requires a JSON payload with timeRange, stepStart and stepEnd; any syntax error or wrong field type causes json.Decoder.Decode to fail and the request is rejected with ErrorBadData (HTTP 400).","triggerScenarios":"Calling /api/v1/funnels/{funnelID}/slow-traces with a malformed JSON body, missing required fields, sending form data instead of application/json, or a timeRange/step field with the wrong type (e.g. string instead of number).","commonSituations":"Frontend sending an empty body on a POST route, proxy stripping the body, typo in field names (step_start vs stepStart), or trailing characters after the JSON object.","solutions":["Validate the JSON body with a linter/curl before sending, ensure field names match StepTransitionRequest's json tags","Set Content-Type: application/json and send a single valid JSON object","Check for empty request body caused by redirects or gateway rewrites"],"exampleFix":"// before\ncurl -X POST /api/v1/funnels/<id>/slow-traces -d ''\n// after\ncurl -X POST /api/v1/funnels/<id>/slow-traces -H 'Content-Type: application/json' \\\n  -d '{\"timeRange\":{\"startTime\":1700000000000,\"endTime\":1700086400000},\"stepStart\":0,\"stepEnd\":1}'","handlingStrategy":"validation","validationCode":"const body = { timeRange: { startTime, endTime }, stepStart, stepEnd };\nif (typeof body.stepStart !== 'number' || typeof body.stepEnd !== 'number') throw new TypeError('step indices must be numbers');\nJSON.stringify(body); // throws on invalid structure","typeGuard":"function isValidStepTransitionRequest(b: unknown): b is StepTransitionRequest {\n  const r = b as any;\n  return !!r && typeof r.stepStart === 'number' && typeof r.stepEnd === 'number'\n    && typeof r.timeRange?.startTime === 'number' && typeof r.timeRange?.endTime === 'number';\n}","tryCatchPattern":"try { await api.post(`/funnels/${id}/slow-traces`, body); } catch (e) { if (e.status === 400) showFormError(e.data.error); else throw e; }","preventionTips":["Always set Content-Type: application/json","Serialize with JSON.stringify rather than hand-building strings","Type the request payload in the client to match the server struct"],"tags":["signoz","funnel","json-decode","bad-request"],"backgroundTag":"request-body-validation-failed","analyzedSha":"5069bf80b08f1f00d7e014eccc09902f9871004f","analyzedAt":"2026-08-28T06:22:12.824Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}