VictoriaMetrics/VictoriaMetrics · error

cannot read ExplicitBounds

Error message

cannot read ExplicitBounds

What it means

This error is returned while decoding an OTLP HistogramDataPoint: field 7 (explicit_bounds, repeated double) failed to be unpacked from the protobuf wire format by easyproto's UnpackDoubles. It means the bytes on the wire for this field are malformed or truncated - the wire type does not match the expected packed/unpacked double encoding, or the payload ends mid-field. The parser is strict and aborts the whole request rather than skipping the bad field.

Source

Thrown at lib/protoparser/opentelemetry/pb/pb.go:1180

			hctx.count, ok = fc.Fixed64()
			if !ok {
				return fmt.Errorf("cannot read Count")
			}
		case 5:
			hctx.sum, ok = fc.Double()
			if !ok {
				return fmt.Errorf("cannot read Sum")
			}
			hctx.hasSum = true
		case 6:
			hctx.bucketCounts, ok = fc.UnpackFixed64s(hctx.bucketCounts)
			if !ok {
				return fmt.Errorf("cannot read BucketCounts")
			}
		case 7:
			hctx.explicitBounds, ok = fc.UnpackDoubles(hctx.explicitBounds)
			if !ok {
				return fmt.Errorf("cannot read ExplicitBounds")
			}
		case 10:
			hctx.flags, ok = fc.Uint32()
			if !ok {
				return fmt.Errorf("cannot read Flags")
			}
		}
	}

	hctx.pushSamples(dctx)

	return nil
}

type histogramDataPointContext struct {
	timestamp      uint64
	count          uint64
	sum            float64

View on GitHub (pinned to 5079fb58f1)

Solutions

  1. Re-serialize the metrics payload with a standard OTLP exporter/protobuf library and retry the request.
  2. Verify the client's Content-Encoding/Content-Type headers match the actual body encoding (gzip vs plain protobuf) and that no intermediary truncates the body (check request body size limits).
  3. Capture the failing request body and decode it with protoc --decode opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest to find the malformed field.
  4. Upgrade both the sender SDK and VictoriaMetrics/protoparser to matching versions, since proto schema drift can change field encodings.

Example fix

// before: client sends gzip-declared body but writes uncompressed bytes
req.Header.Set("Content-Encoding", "gzip")
body := marshalOTLP(req)
// after
var buf bytes.Buffer
gz := gzip.NewWriter(&buf)
gz.Write(marshalOTLP(req))
gz.Close()
req.Body = io.NopCloser(&buf)
Defensive patterns

Strategy: try-catch

Validate before calling

// before sending OTLP bytes, sanity-check they decode with the reference marshaller
var req pb.ExportMetricsServiceRequest
if err := proto.Unmarshal(body, &req); err != nil {
    return fmt.Errorf("invalid OTLP payload: %w", err)
}

Type guard

func isDecodeError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "cannot read ExplicitBounds")
}

Try / catch

err := parser.Unmarshal(req.Body, ...)
if err != nil {
    if strings.Contains(err.Error(), "cannot read") {
        http.Error(w, "malformed OTLP protobuf payload", http.StatusBadRequest)
        return
    }
    http.Error(w, err.Error(), http.StatusInternalServerError)
}

Prevention

When it happens

Trigger: Calling lib/protoparser/opentelemetry Unmarshal (or the /opentelemetry/v1/metrics ingestion path in VictoriaMetrics) with an ExportMetricsServiceRequest whose HistogramDataPoint contains a field 7 with a wire type other than length-delimited (packed) or 64-bit (unpacked), or a truncated double payload.

Common situations: A sender built with a mismatched or hand-rolled protobuf encoder; a proxy/LB or body-size limit truncating the request body mid-message; bytes corrupted by wrong Content-Encoding (e.g. body not actually gzipped/uncompressed as declared); OTLP/HTTP sent to an OTLP/gRPC-style endpoint or vice versa causing payload mangling.

Related errors


AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03). Data as JSON: /api/errors/f40b31c0b285b223. Report an issue: GitHub.