{"record":{"id":"629eda3147617ffb","repo":"thanos-io/thanos","slug":"end-timestamp-must-not-be-before-start-time","errorCode":null,"errorMessage":"end timestamp must not be before start time","messagePattern":"end timestamp must not be before start time","errorType":"validation","errorClass":"api.ApiError","httpStatus":400,"severity":"error","filePath":"pkg/api/query/v1.go","lineNumber":778,"sourceCode":"\tif apiErr != nil {\n\t\treturn nil, nil, apiErr, func() {}\n\t}\n\n\tif engineParam != PromqlEngineThanos {\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.New(\"engine type must be 'thanos'\")}, func() {}\n\t}\n\tqueryParam := qapi.parseQueryParam(r)\n\n\tstart, err := parseTime(r.FormValue(\"start\"))\n\tif err != nil {\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}\n\t}\n\tend, err := parseTime(r.FormValue(\"end\"))\n\tif err != nil {\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}\n\t}\n\tif end.Before(start) {\n\t\terr := errors.New(\"end timestamp must not be before start time\")\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}\n\t}\n\n\tstep, apiErr := qapi.parseStep(r, qapi.defaultRangeQueryStep, int64(end.Sub(start)/time.Second))\n\tif apiErr != nil {\n\t\treturn nil, nil, apiErr, func() {}\n\t}\n\n\tif step <= 0 {\n\t\terr := errors.New(\"zero or negative query resolution step widths are not accepted. Try a positive integer\")\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}\n\t}\n\n\t// For safety, limit the number of returned points per timeseries.\n\t// This is sufficient for 60s resolution for a week or 1h resolution for a year.\n\tif end.Sub(start)/step > 11000 {\n\t\terr := errors.New(\"exceeded maximum resolution of 11,000 points per timeseries. Try decreasing the query resolution (?step=XX)\")\n\t\treturn nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}","sourceCodeStart":760,"sourceCodeEnd":796,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/api/query/v1.go#L760-L796","documentation":"In queryRange, after parsing the `start` and `end` timestamps, the API rejects requests where `end` is earlier than `start`, returning HTTP 400 (api.ErrorBadData). This mirrors Prometheus' range-query semantics and prevents nonsensical or inverted time ranges.","triggerScenarios":"Calling /api/v1/query_range with an `end` timestamp strictly before `start`, e.g. start=2026-01-02T00:00:00Z&end=2026-01-01T00:00:00Z, or where client clocks/timezone handling produce an inverted range.","commonSituations":"Client computing start/end with mixed timezones or RFC3339 vs Unix seconds mixups; dashboards where the 'to' field was set before the 'from' field; off-by-negative duration math when building relative ranges.","solutions":["Swap or recompute start/end so end >= start before sending the request.","Normalize all timestamps to RFC3339/UTC in the client before building the URL.","Add client-side validation: if end.Before(start), reject the query before the HTTP call."],"exampleFix":"// before\nGET /api/v1/query_range?query=up&start=2026-01-02T00:00:00Z&end=2026-01-01T00:00:00Z&step=1m\n// after\nGET /api/v1/query_range?query=up&start=2026-01-01T00:00:00Z&end=2026-01-02T00:00:00Z&step=1m","handlingStrategy":"validation","validationCode":"const start = Date.parse(startStr), end = Date.parse(endStr);\nif (Number.isNaN(start) || Number.isNaN(end)) throw new Error('invalid timestamps');\nif (end < start) throw new Error('end must not be before start');","typeGuard":null,"tryCatchPattern":"const body = await res.json();\nif (body.status === 'error' && /end timestamp must not be before start/.test(body.error)) {\n  // swap or recompute the range client-side before retrying\n}","preventionTips":["Normalize all timestamps to UTC RFC3339 before building requests.","Validate end >= start in every client that constructs range queries.","Beware mixed timezones when users pick 'from'/'to' in dashboards."],"tags":["http-api","query-range","time-range","bad-request"],"backgroundTag":"invalid-query-parameter","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}