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

  1. Validate the JSON body with a linter/curl before sending, ensure field names match StepTransitionRequest's json tags
  2. Set Content-Type: application/json and send a single valid JSON object
  3. 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

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


AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28). Data as JSON: /api/errors/ed58e8b1ac58471e. Report an issue: GitHub.