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

  1. Pass durations in Prometheus format (e.g. 1h, 5m) or seconds as a number
  2. 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

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


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)