thanos-io/thanos · error · api.ApiError

' ' bad engine

Error message

'%s' bad engine

What it means

parseEngineParam validates the 'engine' query parameter against the two supported engines (PromQL 'prometheus' and Thanos 'thanos'); any other value is rejected with ErrorBadData. The message echoes the offending engine name.

Solutions

  1. Use exactly 'prometheus' or 'thanos' (lowercase) for the engine parameter
  2. Omit the parameter to use the server's default engine (-query.promql-engine flag)
  3. Check the Thanos version's supported engine constants (PromqlEnginePrometheus/PromqlEngineThanos)
  4. Fix casing in generated clients

Example fix

// before
GET /api/v1/query?query=up&engine=Thanos
// after
GET /api/v1/query?query=up&engine=thanos
Defensive patterns

Strategy: validation

Validate before calling

const ENGINES = new Set(['prometheus','thanos']);
if (engine !== undefined && !ENGINES.has(engine)) throw new Error(`bad engine: ${engine}`);

Type guard

function isKnownEngine(e) { return e === 'prometheus' || e === 'thanos'; }

Try / catch

try {
  const res = await fetch(urlWithEngine);
  const body = await res.json();
  if (body.errorType === 'bad_data' && /bad engine/.test(body.error)) throw new Error(body.error);
} catch (e) {
  if (/bad engine/.test(e.message)) { /* drop the engine param (use server default) and retry */ }
  throw e;
}

Prevention

When it happens

Trigger: Passing engine=<anything else> on /api/v1/query, /api/v1/query_range or their explain endpoints, e.g. engine=thanos-impl2, engine=PROMETHEUS (case mismatch), or engine=jq.

Common situations: Copying engine options from other engines/tools; attempting to select experimental engines not present in the deployed Thanos version; case-sensitivity mistakes.

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


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/eca5fd3174113ed5. Report an issue: GitHub.

Appendix: source

Thrown at pkg/api/query/v1.go:318

			return false, &api.ApiError{Typ: api.ErrorBadData, Err: errors.Wrapf(err, "'%s' parameter", DedupParam)}
		}
	}
	return enableDeduplication, nil
}

func (qapi *QueryAPI) parseQueryParam(r *http.Request) string {
	return r.FormValue(QueryParam)
}

func (qapi *QueryAPI) parseEngineParam(r *http.Request) (e PromqlEngineType, _ *api.ApiError) {
	param := PromqlEngineType(r.FormValue(EngineParam))
	if param == "" {
		param = qapi.defaultEngine
	}
	switch param {
	case PromqlEnginePrometheus, PromqlEngineThanos:
	default:
		return param, &api.ApiError{Typ: api.ErrorBadData, Err: errors.Errorf("'%s' bad engine", param)}
	}

	return param, nil
}

func (qapi *QueryAPI) parseReplicaLabelsParam(r *http.Request) (replicaLabels []string, _ *api.ApiError) {
	if err := r.ParseForm(); err != nil {
		return nil, &api.ApiError{Typ: api.ErrorInternal, Err: errors.Wrap(err, "parse form")}
	}

	replicaLabels = qapi.replicaLabels
	// Overwrite the cli flag when provided as a query parameter.
	if len(r.Form[ReplicaLabelsParam]) > 0 {
		replicaLabels = r.Form[ReplicaLabelsParam]
	}
	return replicaLabels, nil
}

View on GitHub (pinned to 35b8b99117)