thanos-io/thanos · error

cannot obtain metadata: neither info nor store client found

Error message

cannot obtain metadata: neither info nor store client found

What it means

In pkg/query EndpointSet metadata collection, after trying the /metadata endpoint and gRPC store-info paths, the code returns errors.New(noMetadataEndpointMessage) — "cannot obtain metadata: neither info nor store client found" — when an endpoint provides neither a StoreClient (gRPC store API) nor a working HTTP metadata endpoint. updateEndpoint records this as the endpoint's lastError.

Solutions

  1. Ensure each endpoint in the endpointset actually exposes a Thanos StoreAPI (gRPC) or a valid Thanos HTTP metadata endpoint.
  2. Upgrade sidecar/store components to a version that serves the StoreAPI (/store API or storepb).
  3. Verify endpoint addressing and paths; curl the /metadata endpoint to confirm it responds.
  4. Remove or fix endpoints that are not Thanos store nodes from the endpoint configuration.

Example fix

// before
// endpoint registered with only an HTTP address, no store API
EndpointSet{ Endpoints: []string{"http://prometheus:9090"} }

// after
// register the Thanos Sidecar StoreAPI gRPC endpoint instead
EndpointSet{ Endpoints: []string{"sidecar.example:10901"} }
Defensive patterns

Strategy: validation

Validate before calling

// before adding an endpoint, verify it serves metadata or store API
resp, err := http.Get(endpointURL + "/metadata")
if err != nil || resp.StatusCode != http.StatusOK {
	return fmt.Errorf("endpoint %s lacks metadata endpoint; ensure it exposes Thanos StoreAPI", endpointURL)
}

Prevention

When it happens

Trigger: Endpoint is registered in the EndpointSet but the gRPC StoreClient is unavailable (spec has no store API support) and the HTTP /metadata or /-/ endpoints fail or are absent (e.g. non-Thanos HTTP endpoint, or Sidecar/O storeAPI nil).

Common situations: Adding an HTTP-only endpoint (e.g. plain Prometheus URL without Thanos storeAPI); sidecar version too old to expose StoreAPI; endpoint URL typed wrong so /metadata 404s; mixing node types in --endpoint flag.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at pkg/query/endpointset.go:90

func (es *GRPCEndpointSpec) Addr() string {
	// API address should not change between state changes.
	return es.addr
}

// Metadata method for gRPC endpoint tries to call InfoAPI exposed by Thanos components until context timeout. If we are unable to get metadata after
// that time, we assume that the host is unhealthy and return error.
func (es *endpointRef) Metadata(ctx context.Context, infoClient infopb.InfoClient, storeClient storepb.StoreClient) (*endpointMetadata, error) {
	if infoClient != nil {
		resp, err := infoClient.Info(ctx, &infopb.InfoRequest{}, grpc.WaitForReady(true))
		if err != nil {
			if status.Convert(err).Code() != codes.Unimplemented {
				return nil, err
			}
		} else {
			return &endpointMetadata{resp}, nil
		}
	}
	return nil, errors.New(noMetadataEndpointMessage)
}

// stringError forces the error to be a string
// when marshaled into a JSON.
type stringError struct {
	originalErr error
}

// MarshalJSON marshals the error into a string form.
func (e *stringError) MarshalJSON() ([]byte, error) {
	return json.Marshal(e.originalErr.Error())
}

// Error returns the original underlying error.
func (e *stringError) Error() string {
	return e.originalErr.Error()
}

View on GitHub (pinned to 35b8b99117)