thanos-io/thanos · error

marshal read request

Error message

marshal read request

What it means

startPromRemoteRead marshals the prompb.ReadRequest (with the query and accepted response types) using proto.Marshal before sending it over HTTP. If marshaling fails, the wrapped error "marshal read request" is returned. Failure here is rare since the request proto is built in-process from valid fields.

Solutions

  1. Inspect the prompb.Query passed to Series — verify matchers, start, end timestamps are sane and not nil
  2. Regenerate/align prompb Go code with the Prometheus/Thanos API version in go.mod
  3. Reduce query size/complexity and retry
Defensive patterns

Strategy: validation

Validate before calling

if q == nil || len(q.Matchers) == 0 { return errors.New("invalid query: nil or empty matchers") }

Try / catch

resp, err := store.Series(ctx, req)
if err != nil && strings.Contains(err.Error(), "marshal read request") {
    // inspect the query object passed in; regenerate prompb types
}

Prevention

When it happens

Trigger: proto.Marshal failing on a ReadRequest — practically only when the query contains invalid field state (e.g. nil-required semantics or corrupt matcher data) or an unsupported field produced upstream in the Series call chain.

Common situations: Corrupt or oversized query objects passed through layered query trees; custom builds with mismatched prompb generated code; extremely large queries hitting marshal resource limits.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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

Appendix: source

Thrown at pkg/store/prometheus.go:464

		chks = append(chks, storepb.AggrChunk{
			MinTime: samples[0].Timestamp,
			MaxTime: samples[chunkSize-1].Timestamp,
			Raw:     &storepb.Chunk{Type: enc, Data: cb, Hash: chkHash},
		})

		samples = samples[chunkSize:]
	}

	return chks, nil
}

func (p *PrometheusStore) startPromRemoteRead(ctx context.Context, q *prompb.Query) (presp *http.Response, err error) {
	reqb, err := proto.Marshal(&prompb.ReadRequest{
		Queries:               []*prompb.Query{q},
		AcceptedResponseTypes: p.remoteReadAcceptableResponses,
	})
	if err != nil {
		return nil, errors.Wrap(err, "marshal read request")
	}

	u := *p.base
	u.Path = path.Join(u.Path, "api/v1/read")

	preq, err := http.NewRequest("POST", u.String(), bytes.NewReader(snappy.Encode(nil, reqb)))
	if err != nil {
		return nil, errors.Wrap(err, "unable to create request")
	}
	preq.Header.Add("Content-Encoding", "snappy")
	preq.Header.Set("Content-Type", "application/x-stream-protobuf")
	preq.Header.Set("X-Prometheus-Remote-Read-Version", "0.1.0")

	preq.Header.Set("User-Agent", clientconfig.ThanosUserAgent)
	presp, err = p.client.Do(preq.WithContext(ctx))
	if err != nil {
		return nil, errors.Wrap(err, "send request")
	}

View on GitHub (pinned to 35b8b99117)