thanos-io/thanos · error · ApiError

error parsing request form=

Error message

error parsing request form='%v'

What it means

Returned when r.ParseForm() fails while handling the /api/v1/rules request. ParseForm parses the URL query and (for POST) the body; a malformed query string or unreadable body triggers this. Note a copy-paste quirk: the error text interpolates the MatcherParam constant rather than the actual parse error, and it is surfaced as ErrorInternal (HTTP 500).

Solutions

  1. URL-encode query parameters properly (e.g. use url.Values.Encode / encodeURIComponent for match[] regexes).
  2. Remove or fix malformed percent-escapes in the request URL.
  3. Inspect the wrapped ParseForm error from the HTTP layer for the precise parse failure.
  4. If the confusing message (which prints the param name, not the cause) is a problem, patch v1.go to wrap the actual err.

Example fix

// before
fetch('/api/v1/rules?match[]=' + expr)
// after
fetch('/api/v1/rules?match[]=' + encodeURIComponent(expr))
Defensive patterns

Strategy: validation

Validate before calling

const qs = new URLSearchParams(); qs.set('match[]', expr); const url = `/api/v1/rules?${qs.toString()}`; // ensures valid percent-encoding

Try / catch

try { const r = await fetch(url); if (!r.ok) throw new Error(await r.text()); } catch (e) { console.error('rules request failed:', e.message); }

Prevention

When it happens

Trigger: Any /api/v1/rules request whose URL query string or form body cannot be parsed by net/http — e.g. malformed percent-encoding like '%zz' in the query.

Common situations: Hand-crafted URLs with invalid percent-escapes, proxies mangling the query string, or clients sending a corrupt/malformed POST body to the rules endpoint.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


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

Appendix: source

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

		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) {
			groups, warnings, err = client.Rules(ctx, req)
		})
		if err != nil {
			return nil, nil, &api.ApiError{Typ: api.ErrorInternal, Err: errors.Errorf("error retrieving rules: %v", err)}, func() {}
		}
		return groups, warnings.AsErrors(), nil, func() {}

View on GitHub (pinned to 35b8b99117)