thanos-io/thanos · error

error parsing query string, when enforcing tenenacy

Error message

error parsing query string, when enforcing tenenacy

What it means

EnforceQueryTenancy wraps a PromQL parse failure with this message. When tenancy is enforced, incoming PromQL queries are parsed with extpromql.ParseExpr before injecting tenant label matchers; if the query string is not syntactically valid PromQL, the wrapped error is returned and the query is rejected.

Solutions

  1. Log/inspect the underlying wrapped error, which names the exact parse offset and token
  2. Test the query in a standalone Prometheus/PromQL editor to confirm validity
  3. Fix the client that produces the malformed query (escaping, truncation, encoding)
  4. Check for proxy layers that mangle the query parameter (double-encoding, truncation)

Example fix

// before (malformed)
up{job="foo"
// after
up{job="foo"}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate query client-side (JS)
if (!query || query.trim().length === 0) throw new Error("empty PromQL query");

Try / catch

// Go
rewritten, err := EnforceQueryTenancy(query, tenant, enforce)
if err != nil && strings.Contains(err.Error(), "error parsing query string") {
    http.Error(w, fmt.Sprintf("invalid PromQL: %v", errors.Unwrap(err)), http.StatusBadRequest)
    return
}

Prevention

When it happens

Trigger: EnforceQueryTenancy (called via RewritePromQL or HTTP handlers) receives a malformed query string, e.g. truncated expressions, invalid syntax, or non-PromQL payloads sent to query endpoints.

Common situations: Dashboard/tooling emitting malformed queries; clients URL-encoding incorrectly so operators get mangled; queries cut off by proxies or length limits; users typing invalid PromQL in Grafana pointed through the tenant proxy.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at pkg/tenancy/tenancy.go:154

	md, ok := metadata.FromIncomingContext(ctx)
	if !ok || len(md.Get(DefaultTenantHeader)) == 0 {
		return DefaultTenant, false
	}
	return md.Get(DefaultTenantHeader)[0], true
}

func EnforceQueryTenancy(tenantLabel string, tenant string, query string) (string, error) {
	labelMatcher := &labels.Matcher{
		Name:  tenantLabel,
		Type:  labels.MatchEqual,
		Value: tenant,
	}

	e := injectproxy.NewPromQLEnforcer(false, labelMatcher)

	expr, err := extpromql.ParseExpr(query)
	if err != nil {
		return "", errors.Wrap(err, "error parsing query string, when enforcing tenenacy")
	}

	if err := e.EnforceNode(expr); err != nil {
		return "", errors.Wrap(err, "error enforcing label")
	}

	return expr.String(), nil
}

func getLabelMatchers(formMatchers []string, tenant string, enforceTenancy bool, tenantLabel string) ([][]*labels.Matcher, error) {
	tenantLabelMatcher := &labels.Matcher{
		Name:  tenantLabel,
		Type:  labels.MatchEqual,
		Value: tenant,
	}

	matcherSets := make([][]*labels.Matcher, 0, len(formMatchers))

View on GitHub (pinned to 35b8b99117)