VictoriaMetrics/VictoriaMetrics · error

cannot unmarshal type

Error message

cannot unmarshal type

What it means

Raised at lib/protoparser/datadogv2/parser.go:302 when Resource field 1 (string type) in a DataDog v2 series payload cannot be read: FieldContext.String() returned false because the field is not a valid length-delimited string. The resource, and the request containing it, is rejected.

Source

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

func (r *Resource) unmarshalProtobuf(src []byte) (err error) {
	// message Resource {
	//   string type = 1;
	//   string name = 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:
			typ, ok := fc.String()
			if !ok {
				return fmt.Errorf("cannot unmarshal type")
			}
			r.Type = typ
		case 2:
			name, ok := fc.String()
			if !ok {
				return fmt.Errorf("cannot unmarshal name")
			}
			r.Name = name
		}
	}
	return nil
}

View on GitHub (pinned to 5079fb58f1)

Solutions

  1. Confirm with protoc --decode_raw that field 1 of Resource is wire type 2 and decodes as UTF-8.
  2. Fix the sender so `string type = 1;` is encoded as a length-delimited string via generated proto code.
  3. Align the client's agent-payload proto version with the one VictoriaMetrics parses (commit d7c5dcc).
  4. Log the wrapped inner error, reject the series with 400, and let the client retry with a correct payload.

Example fix

// before: type encoded as numeric enum varint
pb.Resource{Type: pb.ResourceType_HOST} // typed enum, wrong wire type
// after: encode as the string the schema defines
pb.Resource{Type: "host", Name: name}
Defensive patterns

Strategy: validation

Validate before calling

// Resource.type must be a length-delimited string (field 1, wire type 2):
// protoc --decode_raw < resource.bin  =>  "1: \"host\""
if r.GetType() == "" {
	return errors.New("resource.type must be a non-empty string")
}

Try / catch

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

Prevention

When it happens

Trigger: A Resource submessage encodes type (field 1) with a varint/fixed wire type instead of length-delimited, or its string length varint exceeds the remaining submessage bytes.

Common situations: Hand-rolled encoders writing resource type as a numeric enum; sender built from a divergent agent-payload proto; corrupted payloads truncated in transit.

Related errors


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