thanos-io/thanos · error

convert matchers

Error message

convert matchers

What it means

selectFn first converts PromQL label matchers to storepb (gRPC store API) matchers via storepb.PromMatchersToMatchers. This fails when a matcher uses a value or regex the storepb format cannot represent, and the error is wrapped as 'convert matchers'.

Solutions

  1. Simplify the PromQL matchers in the query (avoid exotic regex)
  2. Validate matchers before querying; ensure standard match types (=, !=, =~, !~)
  3. Check Thanos/Prometheus version compatibility of matcher conversion
  4. Inspect the wrapped cause in the error for the exact failing matcher

Example fix

// before
{__name__=~"foo|bar",job=~"(?i)web"} // unsupported regex flags
// after
{__name__=~"foo|bar",job=~"[Ww][Ee][Bb]"}
Defensive patterns

Strategy: validation

Validate before calling

for _, m := range ms {
    switch m.Type {
    case labels.MatchEqual, labels.MatchNotEqual, labels.MatchRegexp, labels.MatchNotRegexp:
    default:
        return fmt.Errorf("unsupported matcher type %v for %s", m.Type, m.Name)
    }
    if _, err := regexp.Compile(m.Value); err != nil {
        return fmt.Errorf("invalid regex for %s: %w", m.Name, err)
    }
}

Type guard

func isStoreSafeMatcher(m *labels.Matcher) bool {
    switch m.Type {
    case labels.MatchEqual, labels.MatchNotEqual, labels.MatchRegexp, labels.MatchNotRegexp:
        _, err := regexp.Compile(m.Value)
        return err == nil
    }
    return false
}

Try / catch

if err := ss.Err(); err != nil {
    var we error
    if errors.As(err, &we) && strings.Contains(err.Error(), "convert matchers") {
        return nil, fmt.Errorf("bad selector: %w", we)
    }
}

Prevention

When it happens

Trigger: Passing a *labels.Matcher with an unsupported match type or malformed regex into querier.Select, which reaches selectFn and fails PromMatchersToMatchers.

Common situations: Queries with unusual regex constructs not supported by the RE2-based store conversion, or third-party clients sending custom matcher types.

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/4533bd994359d297. Report an issue: GitHub.

Appendix: source

Thrown at pkg/query/querier.go:362

	return &lazySeriesSet{create: func() (storage.SeriesSet, bool) {
		defer cancel()
		defer span.Finish()

		// Only gets called once, for the first Next() call of the series set.
		set, ok := <-promise
		if !ok {
			return storage.ErrSeriesSet(errors.New("channel closed before a value received")), false
		}
		return set, set.Next()
	}}
}

const SeriesHashLabelName = "__cf_series_hash__"

func (q *querier) selectFn(ctx context.Context, hints *storage.SelectHints, ms ...*labels.Matcher) (storage.SeriesSet, storepb.SeriesStatsCounter, error) {
	sms, err := storepb.PromMatchersToMatchers(ms...)
	if err != nil {
		return nil, storepb.SeriesStatsCounter{}, errors.Wrap(err, "convert matchers")
	}

	aggrs := aggrsFromFunc(hints.Func)
	maxResolutionMillis := maxResolutionFromSelectHints(q.maxResolutionMillis, hints.Range, hints.Func)

	// TODO(bwplotka): Pass it using the SeriesRequest instead of relying on context.
	ctx = context.WithValue(ctx, store.StoreMatcherKey, q.storeDebugMatchers)

	// TODO(bwplotka): Use inprocess gRPC when we want to stream responses.
	// Currently streaming won't help due to nature of the both PromQL engine which
	// pulls all series before computations anyway.
	resp := &seriesServer{ctx: ctx}
	req := storepb.SeriesRequest{
		MinTime:                 hints.Start,
		MaxTime:                 hints.End,
		Limit:                   int64(hints.Limit),
		Matchers:                sms,
		MaxResolutionWindow:     maxResolutionMillis,

View on GitHub (pinned to 35b8b99117)