thanos-io/thanos · error
cannot parse to a valid duration
Error message
cannot parse %q to a valid duration
What it means
parseDuration input validation: the query API parameter string s could not be interpreted as a duration (neither a float of seconds nor a Prometheus duration like 1h30m). The offending query parameter value is at fault.
Solutions
- Pass durations in Prometheus format (e.g. 1h, 5m) or seconds as a number
- Check the query parameter for typos
Example fix
// before GET /api/v1/query?query=up&timeout=5 minutes // after GET /api/v1/query?query=up&timeout=5m
Defensive patterns
Strategy: validation
Validate before calling
function validDuration(s) {
const d = Number(s);
return !Number.isNaN(d) || /^\d+(ms|s|m|h|d|w|y)$/.test(s);
} Prevention
- Use model.ParseDuration-compatible syntax (e.g. 1h30m is NOT valid here — prefer single-unit or numeric seconds).
- Never pass human-language durations; convert first.
- Trim whitespace from parameters before sending.
When it happens
Trigger: Passing a malformed duration such as `?timeout=abc`, `timeout=5x`, or `timeout=1h30` to any endpoint using parseDuration (e.g. query timeout).
Common situations: Typos in duration units, humanized strings like '5 minutes' not matching Prometheus syntax (`5m`), localization artifacts, or passing empty/unset values that skip validation.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
Related errors
- cannot parse to a valid duration. It overflows int64
- cannot parse to a valid limit
- limit must be non-negative
- invalid metric metadata limit=
- parse federation labels
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/b8013ffcf7c5ad33.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/api/query/v1.go:1613
}
if t, err := time.Parse(time.RFC3339Nano, s); err == nil {
return t, nil
}
return time.Time{}, errors.Errorf("cannot parse %q to a valid timestamp", s)
}
func parseDuration(s string) (time.Duration, error) {
if d, err := strconv.ParseFloat(s, 64); err == nil {
ts := d * float64(time.Second)
if ts > float64(math.MaxInt64) || ts < float64(math.MinInt64) {
return 0, errors.Errorf("cannot parse %q to a valid duration. It overflows int64", s)
}
return time.Duration(ts), nil
}
if d, err := model.ParseDuration(s); err == nil {
return time.Duration(d), nil
}
return 0, errors.Errorf("cannot parse %q to a valid duration", s)
}
// parseLimitParam returning 0 means no limit is to be applied.
func parseLimitParam(s string) (int, error) {
if s == "" {
return 0, nil
}
limit, err := strconv.Atoi(s)
if err != nil {
return 0, errors.Errorf("cannot parse %q to a valid limit", s)
}
if limit < 0 {
return 0, errors.New("limit must be non-negative")
}
return limit, nil
}View on GitHub (pinned to 35b8b99117)