thanos-io/thanos · error

no metadata

Error message

no metadata

What it means

metadataServer.Send rejects any response that carries neither a warning nor metadata payload, returning a bare 'no metadata' error. It guards the stream invariant that every non-warning message must include metadata.

Solutions

  1. Check the version compatibility between cloud proxy and Vizier metadata service and upgrade to matching versions
  2. Inspect the upstream service logs for a node emitting empty responses
  3. Retry the metadata request; if reproducible, report the upstream bug
  4. Handle the error in the stream consumer so one bad message does not abort valid data already received

Example fix

// before
if res.GetMetadata() == nil {
    return errors.New("no metadata")
}
// after
if res.GetMetadata() == nil && res.GetWarning() == "" {
    return errors.New("no metadata in response and no warning present")
}
Defensive patterns

Strategy: type-guard

Type guard

func hasPayload(res *metadatapb.MetricMetadataResponse) bool {
    return res != nil && (res.GetMetadata() != nil || res.GetWarning() != "")
}

Try / catch

if err := streamSend(res); err != nil {
    if strings.Contains(err.Error(), "no metadata") {
        // skip malformed message, continue consuming stream
    }
}

Prevention

When it happens

Trigger: The upstream metadata service sends a MetricMetadataResponse whose metadata field is nil and whose warning is empty.

Common situations: Malformed or truncated upstream responses; a store node bug emitting empty messages; protobuf deserialization yielding a nil payload.

Related errors


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

Appendix: source

Thrown at pkg/metadata/metadata.go:84

	metric string
	limit  int

	warnings    annotations.Annotations
	metadataMap map[string][]metadatapb.Meta
	mu          sync.Mutex
}

func (srv *metadataServer) Send(res *metadatapb.MetricMetadataResponse) error {
	if res.GetWarning() != "" {
		srv.mu.Lock()
		defer srv.mu.Unlock()
		srv.warnings.Add(errors.New(res.GetWarning()))
		return nil
	}

	if res.GetMetadata() == nil {
		return errors.New("no metadata")
	}

	// If limit is set to 0, we don't need to add anything.
	if srv.limit == 0 {
		return nil
	}

	srv.mu.Lock()
	defer srv.mu.Unlock()
	for k, v := range res.GetMetadata().Metadata {
		if metadata, ok := srv.metadataMap[k]; !ok {
			// If limit is set and it is positive, we limit the size of the map.
			if srv.limit < 0 || srv.limit > 0 && len(srv.metadataMap) < srv.limit {
				srv.metadataMap[k] = v.Metas
			}
		} else {
			// There shouldn't be many metadata for one single metric.
		Outer:

View on GitHub (pinned to 35b8b99117)