canopy-network/canopy · error
invalid length at offset %d
Error message
invalid length at offset %d
What it means
When a matching length-delimited (BytesType) field is found, GetRawProtoField reads the value length as a varint. ConsumeVarint returning a negative byte count means the length varint itself is malformed/truncated — the buffer ends inside the varint, so the field's length cannot be determined.
Source
Thrown at lib/codec/codec.go:82
// GetRawProtoField extracts the raw bytes for field number from a proto message
func GetRawProtoField(protoBytes []byte, fieldNumber int) ([]byte, error) {
var offset int
// parse the proto bytes to find a field
for offset < len(protoBytes) {
// decode the field tag (field number + wire type)
fieldNum, wireType, tagLen := protowire.ConsumeTag(protoBytes[offset:])
if tagLen < 0 {
return nil, fmt.Errorf("invalid tag at offset %d", offset)
}
offset += tagLen
// check if this is the field we're looking for
if int(fieldNum) == fieldNumber {
// for length-delimited fields (like messages), we need to read the length
if wireType == protowire.BytesType {
// read the length of the field value
valueLen, lenBytes := protowire.ConsumeVarint(protoBytes[offset:])
if lenBytes < 0 {
return nil, fmt.Errorf("invalid length at offset %d", offset)
}
// calculate the new offset
offset += lenBytes
// extract the field value bytes
if offset+int(valueLen) > len(protoBytes) {
return nil, fmt.Errorf("field value exceeds buffer bounds")
}
// make buffer to return
fieldBytes := make([]byte, valueLen)
// copy into the buffer
copy(fieldBytes, protoBytes[offset:offset+int(valueLen)])
// return the value
return fieldBytes, nil
} else {
// for other wire types, consume the value directly
valueLen := protowire.ConsumeFieldValue(fieldNum, wireType, protoBytes[offset:])
if valueLen < 0 {
return nil, fmt.Errorf("invalid field value at offset %d", offset)View on GitHub (pinned to ee8197d91d)
Solutions
- Re-read or re-fetch the complete message bytes; confirm length matches the originally marshaled size.
- Validate with proto.Unmarshal on the full buffer before calling GetRawProtoField to detect truncation early.
- Fix the code that slices/passes a partial buffer to GetRawProtoField.
Example fix
// before chunk := buf[:len(buf)-2] // accidental truncation raw, _ := codec.GetRawProtoField(chunk, 1) // after raw, err := codec.GetRawProtoField(buf, 1)
Defensive patterns
Strategy: validation
Validate before calling
var probe pb.Event
if err := proto.Unmarshal(data, &probe); err != nil {
return fmt.Errorf("truncated/malformed proto bytes: %w", err)
} Try / catch
raw, err := codec.GetRawProtoField(data, fieldNum)
if err != nil && strings.Contains(err.Error(), "invalid length") {
return fmt.Errorf("truncated buffer at length prefix: %w", err)
} Prevention
- Verify byte counts on storage/network reads before parsing.
- Never pass manually sliced fragments of a message to raw field extraction.
- Include integrity checks (length headers, checksums) on persisted blobs.
When it happens
Trigger: GetRawProtoField on a truncated proto buffer where the tag of the target field is present but the varint length prefix is cut off.
Common situations: Partial reads from storage or network producing truncated payloads; off-by-one slicing of the proto bytes; corruption during transport or persistence.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- field value exceeds buffer bounds
- invalid field value at offset %d
- invalid tag at offset %d
- ErrFieldNotFound
- unsupported wire type %d
AI-assisted analysis of canopy-network/canopy@ee8197d91d (2026-09-06).
Data as JSON: /api/errors/448a42c6196f691c.
Report an issue: GitHub.