thanos-io/thanos · error
invalid parameter ;
Error message
invalid parameter %q; %v
What it means
decorateWithParamName wraps errors from decoding/validating a query-range request parameter, producing 'invalid parameter "<field>"; <detail>'. If the error is a gRPC status error it becomes an httpgrpc HTTP error carrying the status code; otherwise it is a plain fmt.Errorf.
Solutions
- Read the field name and detail in the message to see which parameter is invalid.
- Fix the client request: use valid duration formats (e.g. '1h'), numeric timestamps in seconds, and a step > 0.
- Check start/end are within the configured retention/query window.
- Catch the httpgrpc error client-side and surface the parameter name back to the user instead of a generic 500.
Example fix
// before /api/v1/query_range?query=up&start=now-1h&end=now&step=0 // after /api/v1/query_range?query=up&start=1690000000&end=1690003600&step=15
Defensive patterns
Strategy: validation
Validate before calling
func validQueryRange(start, end int64, step time.Duration) error {
if step <= 0 { return fmt.Errorf("step must be > 0") }
if start >= end { return fmt.Errorf("start must be before end") }
return nil
} Try / catch
resp, err := frontend.QueryRange(ctx, req)
if err != nil {
var hg httpgrpc.HTTPClientError
if errors.As(err, &hg) && strings.Contains(err.Error(), "invalid parameter") {
return http.StatusBadRequest // surface which param is bad
}
return err
} Prevention
- Validate duration/step/timestamp formats client-side before sending.
- Keep start/end within retention and use epoch seconds.
- Surface the parameter name from the error message to end users.
When it happens
Trigger: Calling a query-range endpoint (Prometheus API path through queryrange middleware) with a malformed parameter value that downstream gRPC decoding rejects — e.g. bad timeout, invalid step, unparseable start/end timestamps.
Common situations: Dashboards sending step/timeout values with wrong units; start/end outside retention; query parameter strings that fail protobuf/JSON decoding in the query-frontend.
Understand the failure class
Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.
Related errors
- ID cannot be empty
- Action cannot be empty
- invalid targets parameter state=
- invalid rules parameter type=
- unsupported format for label
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/e1a7393a145ac392.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cortex/querier/queryrange/query_range.go:891
}
return 0, httpgrpc.Errorf(http.StatusBadRequest, "cannot parse %q to a valid duration", s)
}
func encodeTime(t int64) string {
f := float64(t) / 1.0e3
return strconv.FormatFloat(f, 'f', -1, 64)
}
func encodeDurationMs(d int64) string {
return strconv.FormatFloat(float64(d)/float64(time.Second/time.Millisecond), 'f', -1, 64)
}
func decorateWithParamName(err error, field string) error {
errTmpl := "invalid parameter %q; %v"
if status, ok := status.FromError(err); ok {
return httpgrpc.Errorf(int(status.Code()), errTmpl, field, status.Message())
}
return fmt.Errorf(errTmpl, field, err)
}
func PrometheusResponseQueryableSamplesStatsPerStepJsoniterDecode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
if !iter.ReadArray() {
iter.ReportError("queryrange.PrometheusResponseQueryableSamplesStatsPerStep", "expected [")
return
}
t := model.Time(iter.ReadFloat64() * float64(time.Second/time.Millisecond))
if !iter.ReadArray() {
iter.ReportError("queryrange.PrometheusResponseQueryableSamplesStatsPerStep", "expected ,")
return
}
v := iter.ReadInt64()
if iter.ReadArray() {
iter.ReportError("queryrange.PrometheusResponseQueryableSamplesStatsPerStep", "expected ]")View on GitHub (pinned to 35b8b99117)