thanos-io/thanos · error

proxy LabelNames()

Error message

proxy LabelNames()

What it means

LabelNames proxies the gRPC LabelNames RPC to all stores; any error returned by proxy.LabelNames is wrapped as 'proxy LabelNames()'. This is the umbrella error for store-side RPC failures during label name lookups.

Solutions

  1. Check store health and connectivity; inspect the wrapped RPC error
  2. Verify store address configuration and service discovery
  3. Increase query/store timeouts if under heavy load
  4. Retry once stores recover; check thanos query store status in UI/API
Defensive patterns

Strategy: retry

Validate before calling

// pre-check store reachability
if !allStoresHealthy(ctx, stores, 2*time.Second) {
    return errors.New("stores unhealthy; skip LabelNames fan-out")
}

Try / catch

names, warns, err := q.LabelNames(ctx, hints, matchers...)
if err != nil {
    if strings.Contains(err.Error(), "proxy LabelNames()") {
        return retryBackoff(ctx, 3, func() error { return fetchNames() })
    }
    return err
}

Prevention

When it happens

Trigger: Calling LabelNames while stores are unreachable, return remote errors, or the context deadline expires during the RPC fan-out.

Common situations: Store gateway restart, misconfigured store addresses, TLS handshake failures, heavy cardinality causing RPC timeouts.

Related errors


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

Appendix: source

Thrown at pkg/query/querier.go:503

	if hints == nil {
		hints = &storage.LabelHints{}
	}

	req := &storepb.LabelNamesRequest{
		PartialResponseStrategy: q.partialResponseStrategy,
		Start:                   q.mint,
		End:                     q.maxt,
		Matchers:                pbMatchers,
		Limit:                   int64(hints.Limit),
	}

	if q.isDedupEnabled() {
		req.WithoutReplicaLabels = q.replicaLabels
	}

	resp, err := q.proxy.LabelNames(ctx, req)
	if err != nil {
		return nil, nil, errors.Wrap(err, "proxy LabelNames()")
	}

	var warns annotations.Annotations
	for _, w := range resp.Warnings {
		warns.Add(errors.New(w))
	}

	return resp.Names, warns, nil
}

func (q *querier) Close() error { return nil }

// maxResolutionFromSelectHints finds the max possible resolution by inferring from the promql query.
func maxResolutionFromSelectHints(maxResolutionMillis int64, hintsRange int64, hintsFunc string) int64 {
	if hintsRange > 0 {
		if _, ok := promqlFuncRequiresTwoSamples[hintsFunc]; ok {
			maxResolutionMillis = min(maxResolutionMillis, hintsRange/2)
		}

View on GitHub (pinned to 35b8b99117)