VictoriaMetrics/VictoriaMetrics · error

cannot read Flags

Error message

cannot read Flags

What it means

Field 8 of NumberDataPoint is flags, a uint32. fc.Uint32() returns ok=false when field 8 arrives with a wire type other than varint (type 0) — e.g. it was encoded as fixed32/fixed64 or length-delimited — so the decoder returns 'cannot read Flags'. Flags carry data-point flags such as the no-recorded-value mask, so a wrong encoding also silently corrupts flag semantics if forced.

Source

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

			timestamp, ok = fc.Fixed64()
			if !ok {
				return fmt.Errorf("cannot read TimeUnixNano")
			}
		case 4:
			value, ok = fc.Double()
			if !ok {
				return fmt.Errorf("cannot read DoubleValue")
			}
		case 6:
			intValue, ok := fc.Sfixed64()
			if !ok {
				return fmt.Errorf("cannot read IntValue")
			}
			value = float64(intValue)
		case 8:
			flags, ok = fc.Uint32()
			if !ok {
				return fmt.Errorf("cannot read Flags")
			}
		}
	}

	dctx.mp.PushSample(&dctx.mm, "", &dctx.ls, timestamp, value, flags)

	return nil
}

// Sum represents the corresponding OTEL protobuf message
//
// See https://github.com/open-telemetry/opentelemetry-proto/blob/049d4332834935792fd4dbd392ecd31904f99ba2/opentelemetry/proto/metrics/v1/metrics.proto#L240
type Sum struct {
	DataPoints  []*NumberDataPoint
	IsMonotonic bool
}

func (s *Sum) marshalProtobuf(mm *easyproto.MessageMarshaler) {

View on GitHub (pinned to 5079fb58f1)

Solutions

  1. Encode flags as a varint uint32 (AppendUint32, wire type 0) exactly as metrics.proto declares.
  2. Regenerate serialization code from the canonical opentelemetry-proto file.
  3. Verify field 8's wire type with protoc --decode on the producer's output.
  4. Use the official OTel SDK marshaller so flags encoding matches the schema.

Example fix

// before: flags as fixed32
mm.AppendFixed32(8, flags)

// after: flags as varint uint32
mm.AppendUint32(8, flags)
Defensive patterns

Strategy: validation

Validate before calling

// Producer-side: flags must be varint uint32 on field 8
var mm easyproto.MessageMarshaler
mm.AppendUint32(8, flags) // wire type 0
// wrong: mm.AppendFixed32(8, flags) -> "cannot read Flags"

Type guard

func field8IsVarint(dataPointBytes []byte) bool {
    return scanWireType(dataPointBytes, 8) == 0
}

Try / catch

if err := importer.ImportOtlpMetrics(ctx, payload); err != nil {
    if strings.Contains(err.Error(), "cannot read Flags") {
        log.Error("flags field 8 not encoded as varint uint32", "err", err)
        return errBadProducer
    }
    return err
}

Prevention

When it happens

Trigger: Producer encodes flags as fixed32/fixed64 or bytes instead of varint; flags field declared as a different type in a modified .proto; corrupted or fuzzed bytes on field 8.

Common situations: Hand-rolled serializers using AppendFixed32 for flags; generated code from a tweaked .proto (fixed32 flags); intermediary components rewriting datapoints; fuzz tests.

Related errors


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