SigNoz/signoz · error · model.ApiError
invalid request body: %v
Error message
invalid request body: %v
What it means
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).
Source
Thrown at pkg/query-service/app/http_handler.go:4379
vars := mux.Vars(r)
funnelID := vars["funnel_id"]
claims, err := authtypes.ClaimsFromContext(r.Context())
if err != nil {
render.Error(w, err)
return
}
funnel, err := aH.Signoz.Modules.TraceFunnel.Get(r.Context(), valuer.MustNewUUID(funnelID), valuer.MustNewUUID(claims.OrgID))
if err != nil {
RespondError(w, &model.ApiError{Typ: model.ErrorNotFound, Err: fmt.Errorf("funnel not found: %v", err)}, nil)
return
}
var req traceFunnels.StepTransitionRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
RespondError(w, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("invalid request body: %v", err)}, nil)
return
}
chq, err := traceFunnelsModule.GetSlowestTraces(funnel, req.TimeRange, req.StepStart, req.StepEnd)
if err != nil {
RespondError(w, &model.ApiError{Typ: model.ErrorInternal, Err: fmt.Errorf("error building clickhouse query: %v", err)}, nil)
return
}
results, err := aH.reader.GetListResultV3(r.Context(), chq.Query)
if err != nil {
RespondError(w, &model.ApiError{Typ: model.ErrorInternal, Err: fmt.Errorf("error converting clickhouse results to list: %v", err)}, nil)
return
}
aH.Respond(w, results)
}
func (aH *APIHandler) handleFunnelErrorTraces(w http.ResponseWriter, r *http.Request) {View on GitHub (pinned to 5069bf80b0)
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
Example fix
// before
curl -X POST /api/v1/funnels/<id>/slow-traces -d ''
// after
curl -X POST /api/v1/funnels/<id>/slow-traces -H 'Content-Type: application/json' \
-d '{"timeRange":{"startTime":1700000000000,"endTime":1700086400000},"stepStart":0,"stepEnd":1}' Defensive patterns
Strategy: validation
Validate before calling
const body = { timeRange: { startTime, endTime }, stepStart, stepEnd };
if (typeof body.stepStart !== 'number' || typeof body.stepEnd !== 'number') throw new TypeError('step indices must be numbers');
JSON.stringify(body); // throws on invalid structure Type guard
function isValidStepTransitionRequest(b: unknown): b is StepTransitionRequest {
const r = b as any;
return !!r && typeof r.stepStart === 'number' && typeof r.stepEnd === 'number'
&& typeof r.timeRange?.startTime === 'number' && typeof r.timeRange?.endTime === 'number';
} Try / catch
try { await api.post(`/funnels/${id}/slow-traces`, body); } catch (e) { if (e.status === 400) showFormError(e.data.error); else throw e; } Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- error decoding request: %v
- couldn't JSON decode existingFilter: %w
- cannot parse the request body: %v
- error while getting ttl. ttl type should be metrics|traces,
- ErrorID missing from params
AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28).
Data as JSON: /api/errors/ed58e8b1ac58471e.
Report an issue: GitHub.