thanos-io/thanos · error · ApiError

invalid rules parameter type=

Error message

invalid rules parameter type='%v'

What it means

Returned by the /api/v1/rules endpoint when the 'type' query parameter is a non-empty value that doesn't match a RulesRequest_Type enum value (ALL, ALERT, RECORD, or their variants). Like the targets state check, the value is uppercased and looked up in the protobuf enum map; unknown non-empty values yield ErrorBadData (HTTP 400).

Solutions

  1. Use one of the accepted values: all, alert, or record (case-insensitive).
  2. Omit the 'type' parameter to get all rules.
  3. Consult rulespb.RulesRequest_Type in pkg/store/labelpb or rules proto for exact enum names.

Example fix

// before
curl 'http://query:9090/api/v1/rules?type=alerting'
// after
curl 'http://query:9090/api/v1/rules?type=alert'
Defensive patterns

Strategy: validation

Validate before calling

const allowed = ['all','alert','record'];
const typ = params.get('type');
if (typ && !allowed.includes(typ.toLowerCase())) throw new Error(`invalid type='${typ}'; use all|alert|record`);

Prevention

When it happens

Trigger: GET /api/v1/rules?type=alerting — only values matching the RulesRequest_Type enum (case-insensitive: all, alert, record) are accepted.

Common situations: Using Prometheus terminology like 'alerting'/'recording' instead of the proto enum values 'alert'/'record', typos, or assuming empty string means invalid — an empty type is allowed and defaults to ALL.

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/5ec7fc70f82911b5. Report an issue: GitHub.

Appendix: source

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

	if enablePartialResponse {
		ps = storepb.PartialResponseStrategy_WARN
	}

	return func(r *http.Request) (any, []error, *api.ApiError, func()) {
		span, ctx := tracing.StartSpan(r.Context(), "receive_http_request")
		defer span.Finish()

		var (
			groups   *rulespb.RuleGroups
			warnings annotations.Annotations
			err      error
		)

		typeParam := r.URL.Query().Get("type")
		typ, ok := rulespb.RulesRequest_Type_value[strings.ToUpper(typeParam)]
		if !ok {
			if typeParam != "" {
				return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.Errorf("invalid rules parameter type='%v'", typeParam)}, func() {}
			}
			typ = int32(rulespb.RulesRequest_ALL)
		}

		if err := r.ParseForm(); err != nil {
			return nil, nil, &api.ApiError{Typ: api.ErrorInternal, Err: errors.Errorf("error parsing request form='%v'", MatcherParam)}, func() {}
		}

		// TODO(bwplotka): Allow exactly the same functionality as query API: passing replica, dedup and partial response as HTTP params as well.
		req := &rulespb.RulesRequest{
			Type:                    rulespb.RulesRequest_Type(typ),
			PartialResponseStrategy: ps,
			MatcherString:           r.Form[MatcherParam],
			RuleName:                r.Form[RuleNameParam],
			RuleGroup:               r.Form[RuleGroupParam],
			File:                    r.Form[FileParam],
		}
		tracing.DoInSpan(ctx, "retrieve_rules", func(ctx context.Context) {

View on GitHub (pinned to 35b8b99117)