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

  1. Read the field name and detail in the message to see which parameter is invalid.
  2. Fix the client request: use valid duration formats (e.g. '1h'), numeric timestamps in seconds, and a step > 0.
  3. Check start/end are within the configured retention/query window.
  4. 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

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


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)