SigNoz/signoz · error · model.ApiError
cannot parse the request body: %v
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.
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 typeView on GitHub (pinned to 5069bf80b0)
Solutions
- Validate the body against the QueryRangeParamsV3 schema (start/end in microseconds, compositeQuery with panelType and queries)
- Send Content-Type: application/json and a well-formed body
- 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
- Generate request payloads from typed structs (Go/TS types matching v3)
- Always set Content-Type: application/json
- Validate timestamps are numeric microseconds
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
- invalid request body: %v
- error decoding request: %v
- couldn't JSON decode existingFilter: %w
- 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/87adf26ceaed7781.
Report an issue: GitHub.