VictoriaMetrics/VictoriaMetrics · error

cannot unmarshal value

Error message

cannot unmarshal value

What it means

Raised at lib/protoparser/datadogv2/parser.go:258 when Point field 1 (double value) in a DataDog v2 series payload cannot be read: FieldContext.Double() returned false because the field's wire type is not fixed64 (the protobuf encoding of double). The point, and thus the request, is rejected.

Source

Thrown at lib/protoparser/datadogv2/parser.go:258

func (pt *Point) unmarshalProtobuf(src []byte) (err error) {
	// message Point {
	//   double value = 1;
	//   int64 timestamp = 2;
	// }
	//
	// See https://github.com/DataDog/agent-payload/blob/d7c5dcc63970d0e19678a342e7718448dd777062/proto/metrics/agent_payload.proto
	var fc easyproto.FieldContext
	for len(src) > 0 {
		src, err = fc.NextField(src)
		if err != nil {
			return fmt.Errorf("cannot unmarshal next field: %w", err)
		}
		switch fc.FieldNum {
		case 1:
			value, ok := fc.Double()
			if !ok {
				return fmt.Errorf("cannot unmarshal value")
			}
			pt.Value = value
		case 2:
			timestamp, ok := fc.Int64()
			if !ok {
				return fmt.Errorf("cannot unmarshal timestamp")
			}
			pt.Timestamp = timestamp
		}
	}
	return nil
}

// Resource is series resource from DataDog POST request to /api/v2/series
//
// See https://docs.datadoghq.com/api/latest/metrics/#submit-metrics
type Resource struct {
	Name string `json:"name"`

View on GitHub (pinned to 5079fb58f1)

Solutions

  1. Verify field 1 of the Point message is wire type 1 (fixed64) via protoc --decode_raw.
  2. Fix the sender to declare `double value = 1;` in the Point proto and regenerate the encoder.
  3. Update the sending SDK/agent to the official agent-payload version.
  4. Log the wrapped inner error and reject the offending series rather than accepting zero values.

Example fix

// before: value written as varint float bits
buf = appendVarint(buf, math.Float64bits(v))
// after: declare double in proto so it is fixed64-encoded
// message Point { double value = 1; int64 timestamp = 2; }
proto.Marshal(&pb.Point{Value: v, Timestamp: ts})
Defensive patterns

Strategy: validation

Validate before calling

// Point.value must be a double (fixed64, wire type 1):
// protoc --decode_raw < point.bin  =>  "1: 0x4059000000000000"
if math.IsNaN(value) || math.IsInf(value, 0) {
	// still encodable, but ensure it goes through proto.Marshal, not hand-rolled encoding
	_ = proto.Marshal(&pb.Point{Value: value, Timestamp: ts})
}

Try / catch

if err := datadogv2.UnmarshalProtobuf(&req, body); err != nil {
	if strings.Contains(err.Error(), "cannot unmarshal value") {
		log.Printf("point value encoded with wrong wire type: %v", err)
	}
	http.Error(w, "bad point value", http.StatusBadRequest)
	return
}

Prevention

When it happens

Trigger: A Point submessage encodes value (field 1) as varint/fixed32/length-delimited instead of fixed64, or the field data is truncated before 8 bytes.

Common situations: Hand-rolled encoders writing float values as varints; clients built against a proto where value was declared as a different type; corrupt payloads after queueing/retry pipelines.

Related errors


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