thanos-io/thanos · error · api.ApiError
engine type must be 'thanos'
Error message
engine type must be 'thanos'
What it means
The query_explain endpoint only supports the Thanos engine because explain requires engine.ExplainableQuery. If the `engine` request parameter parses successfully but is anything other than 'thanos', queryExplain returns an HTTP 400 (api.ErrorBadData) with this message.
Solutions
- Set `engine=thanos` in the query_explain request.
- Remove the engine parameter only if 'thanos' is the configured default; otherwise pass it explicitly.
- Stop calling query_explain if you must use the Prometheus engine — explain is unsupported there.
Example fix
// before GET /api/v1/query_explain?query=up&engine=prometheus // after GET /api/v1/query_explain?query=up&engine=thanos
Defensive patterns
Strategy: validation
Validate before calling
if (engine !== undefined && engine !== 'thanos') {
throw new Error("query_explain only supports engine='thanos'");
} Type guard
const isThanosEngine = (e) => e === undefined || e === 'thanos';
Try / catch
const body = await res.json();
if (body.status === 'error' && /engine type must be 'thanos'/.test(body.error)) {
// correct the engine parameter and retry once
} Prevention
- Hardcode engine=thanos for explain endpoints in clients.
- Don't share a generic request builder between plain query and explain calls without an engine override.
- Validate engine config values against the 'thanos'/'prometheus' enum client-side.
When it happens
Trigger: Calling /api/v1/query_explain with `engine=prometheus` or any other value than 'thanos'.
Common situations: Copy-pasting query URLs between the regular query endpoint (which accepts prometheus) and the explain endpoint; clients with a configurable engine defaulting to prometheus while also calling explain.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- could not unmarshal parameter
- end timestamp must not be before start time
- zero or negative query resolution step widths are not…
- ULID is not valid
- not supported marker
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/213ec1f0998c0040.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/api/query/v1.go:497
Chunks: s.Chunks,
Samples: s.Samples,
})
}
}
for _, c := range a.Children {
analysis.Children = append(analysis.Children, processAnalysis(c, tracker))
}
return analysis
}
func (qapi *QueryAPI) queryExplain(r *http.Request) (any, []error, *api.ApiError, func()) {
engineParam, apiErr := qapi.parseEngineParam(r)
if apiErr != nil {
return nil, nil, apiErr, func() {}
}
if engineParam != PromqlEngineThanos {
return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.New("engine type must be 'thanos'")}, func() {}
}
queryParam := qapi.parseQueryParam(r)
ts, err := parseTimeParam(r, "time", qapi.baseAPI.Now())
if err != nil {
return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}
}
ctx := r.Context()
if to := r.FormValue("timeout"); to != "" {
var cancel context.CancelFunc
timeout, err := parseDuration(to)
if err != nil {
return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}
}
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()View on GitHub (pinned to 35b8b99117)