thanos-io/thanos · error

expected type *parser.VectorSelector, got %T

Error message

expected type *parser.VectorSelector, got %T

What it means

ParseMetricSelector parses a PromQL expression and then asserts that the resulting AST node is a *parser.VectorSelector so it can return the label matchers. If the parsed expression is any other node type (aggregate, matrix selector, binary expression, etc.), this type-assertion error is returned.

Solutions

  1. Use a bare instant-vector selector expression, e.g. 'up{job="prometheus"}'.
  2. Remove aggregation functions, [range] selectors, and operators from the expression.
  3. Pre-validate the string matches a metric-selector shape (optional metric name plus {} label matchers).

Example fix

// before
ParseMetricSelector("sum(rate(http_requests_total[5m]))")
// after
ParseMetricSelector("http_requests_total")
Defensive patterns

Strategy: validation

Validate before calling

func looksLikeSelector(s string) bool {
  return !strings.ContainsAny(s, "+") && !strings.Contains(s, "[") &&
    !strings.HasPrefix(s, "sum(") && !strings.HasPrefix(s, "rate(")
}

Type guard

expr, ok := parsed.(*parser.VectorSelector)
if !ok { return fmt.Errorf("not a vector selector") }

Try / catch

ms, err := extpromql.ParseMetricSelector(q)
if err != nil { return nil, fmt.Errorf("store selector must be a bare metric selector: %w", err) }

Prevention

When it happens

Trigger: Passing a non-instant-vector selector expression to ParseMetricSelector via ParseStore, parseMatchersParam, parseStoreDebugMatchersParam, or UnmarshalYAML — e.g. 'sum(rate(foo[5m]))', 'foo[5m]', 'up + 1', or a scalar.

Common situations: Store --selector and rule matchers configs that accidentally contain full PromQL queries instead of bare metric selectors; users copying dashboard queries into matcher fields.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at pkg/extpromql/parser.go:40

	maps.Copy(allFuncs, parse.XFunctions)
	p := parser.NewParser(input, parser.WithFunctions(allFuncs))
	defer p.Close()
	return p.ParseExpr()
}

// ParseMetricSelector parses the provided textual metric selector into a list of
// label matchers.
func ParseMetricSelector(input string) ([]*labels.Matcher, error) {
	expr, err := ParseExpr(input)
	// because of the AST checking present in the ParseExpr function,
	// we need to ignore the error if it is just the check for empty name matcher.
	if err != nil && !isEmptyNameMatcherErr(err) {
		return nil, err
	}

	vs, ok := expr.(*parser.VectorSelector)
	if !ok {
		return nil, fmt.Errorf("expected type *parser.VectorSelector, got %T", expr)
	}

	return vs.LabelMatchers, nil
}

func isEmptyNameMatcherErr(err error) bool {
	var parseErrs parser.ParseErrors
	if errors.As(err, &parseErrs) {
		return len(parseErrs) == 1 &&
			strings.HasSuffix(parseErrs[0].Error(), "vector selector must contain at least one non-empty matcher")
	}

	return false
}

View on GitHub (pinned to 35b8b99117)