thanos-io/thanos · error

unexpected result size

Error message

unexpected result size %d

What it means

After successfully unmarshaling the remote-read response, fetchSampledResponse requires exactly one query result (it sent exactly one prompb.Query). If data.Results has any length other than 1, errors.Errorf("unexpected result size %d") is returned. This is an invariant check against a remote endpoint that returned a different number of results than requested.

Solutions

  1. Verify the remote endpoint is a standard Prometheus with remote read returning exactly one result per query
  2. Check server version compatibility; upgrade Prometheus or pin a known-good version
  3. Inspect response with curl to confirm result count matches the single query sent
  4. If using a proxy/cache, bypass it to rule out stale or aggregated responses
Defensive patterns

Strategy: validation

Validate before calling

// confirm endpoint honors one-query-per-request remote read
resp, _ := http.Post(baseURL+"/api/v1/read", "application/x-protobuf", body)
// decode and assert len(results)==1 before production use

Try / catch

series, err := store.Series(ctx, req)
if err != nil && strings.Contains(err.Error(), "unexpected result size") {
    // upstream returned wrong shape: fall back to another store or fail the query
}

Prevention

When it happens

Trigger: The upstream Prometheus returns a ReadResponse containing zero results or multiple results — e.g. a non-standard/older Prometheus implementation, a compatible remote-read server (Thanos, Cortex) that responds differently, or a proxy returning a cached/mismatched response.

Common situations: Pointing the store at Thanos/Cortex/other remote-read implementations with divergent result semantics; version drift where the server batch-responses differently; misrouted requests returning another query's cached result.

Related errors


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

Appendix: source

Thrown at pkg/store/prometheus.go:422

	sb := p.getBuffer()
	var decomp []byte
	tracing.DoInSpan(ctx, "decompress_response", func(ctx context.Context) {
		decomp, err = snappy.Decode(*sb, buf.Bytes())
	})
	defer p.putBuffer(sb)
	if err != nil {
		return nil, errors.Wrap(err, "decompress response")
	}

	var data prompb.ReadResponse
	tracing.DoInSpan(ctx, "unmarshal_response", func(ctx context.Context) {
		err = proto.Unmarshal(decomp, &data)
	})
	if err != nil {
		return nil, errors.Wrap(err, "unmarshal response")
	}
	if len(data.Results) != 1 {
		return nil, errors.Errorf("unexpected result size %d", len(data.Results))
	}

	for _, ts := range data.Results[0].Timeseries {
		labelpb.ReAllocZLabelsStrings(&ts.Labels)
	}

	return &data, nil
}

func (p *PrometheusStore) chunkSamples(series *prompb.TimeSeries, maxSamplesPerChunk int, calculateChecksums bool) (chks []storepb.AggrChunk, err error) {
	samples := series.Samples
	hasher := hashPool.Get().(hash.Hash64)
	defer hashPool.Put(hasher)

	for len(samples) > 0 {
		chunkSize := min(len(samples), maxSamplesPerChunk)

		enc, cb, err := p.encodeChunk(samples[:chunkSize])

View on GitHub (pinned to 35b8b99117)