SigNoz/signoz · error · model.ApiError

cannot parse the request body

Error message

cannot parse the request body: %v

What it means

ParseQueryRangeParams failed to JSON-decode the POST body into v3.QueryRangeParamsV3, returning ErrorBadData. Any malformed JSON or schema mismatch (wrong types, unknown enum values for panelType, etc.) triggers it.

Solutions

  1. Validate the body against the QueryRangeParamsV3 schema (start/end in microseconds, compositeQuery with panelType and queries)
  2. Send Content-Type: application/json and a well-formed body
  3. Capture the exact body and decode it locally with json.Decoder to see the field-level error

Example fix

// before
curl -X POST /api/v3/query_range -d '{"start": "now"}'
// after
curl -X POST /api/v3/query_range -H 'Content-Type: application/json' -d '{"start":1700000000000000,"end":1700003600000000,"compositeQuery":{"panelType":"graph","builderQueries":{}}}'
Defensive patterns

Strategy: try-catch

Validate before calling

var p v3.QueryRangeParamsV3
if err := json.NewDecoder(bytes.NewReader(body)).Decode(&p); err != nil { return fmt.Errorf("body does not match QueryRangeParamsV3: %v", err) }

Try / catch

On 400 with 'cannot parse the request body', log the raw body and the wrapped json error to identify the exact offending field.

Prevention

When it happens

Trigger: POST /api/v3/query_range with invalid JSON, wrong field types (e.g. start as string when number expected), or a compositeQuery shape that doesn't match the struct.

Common situations: Manually crafting API payloads instead of using the UI; version drift where the payload schema changed; proxies stripping or truncating the body; sending an empty body.

Related errors


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

Appendix: source

Thrown at pkg/query-service/app/parser.go:761

			IsSelectAll: true,
			FieldType:   "scalar",
		})
	}
	transformer := chVariables.NewQueryTransformer(query, varsForTransform)
	transformedQuery, err := transformer.Transform()
	if err != nil {
		slog.Warn("failed to transform clickhouse query", "query", query, signozerrors.Attr(err))
	}
	slog.Info("transformed clickhouse query", "transformed_query", transformedQuery, "original_query", query)
}

func ParseQueryRangeParams(r *http.Request) (*v3.QueryRangeParamsV3, *model.ApiError) {

	var queryRangeParams *v3.QueryRangeParamsV3

	// parse the request body
	if err := json.NewDecoder(r.Body).Decode(&queryRangeParams); err != nil {
		return nil, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("cannot parse the request body: %v", err)}
	}

	// sanitize the request body
	queryRangeParams.CompositeQuery.Sanitize()

	// validate the request body
	if err := validateQueryRangeParamsV3(queryRangeParams); err != nil {
		return nil, &model.ApiError{Typ: model.ErrorBadData, Err: err}
	}

	// Clamp the top-level Step for PromQL
	if queryRangeParams.CompositeQuery.QueryType == v3.QueryTypePromQL {
		if minStep := common.MinAllowedStepInterval(queryRangeParams.Start, queryRangeParams.End); queryRangeParams.Step < minStep {
			queryRangeParams.Step = minStep
		}
	}

	// prepare the variables for the corresponding query type

View on GitHub (pinned to 5069bf80b0)