{"record":{"id":"ea689b9d05e0b507","repo":"hyperledger/fabric","slug":"error-decoding-raw-bytes-with-proto-buffer","errorCode":null,"errorMessage":"error decoding raw bytes with proto.Buffer","messagePattern":"error decoding raw bytes with proto\\.Buffer","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/ledger/blkstorage/protobuf_util.go","lineNumber":40,"sourceCode":"func newBuffer(b []byte) *buffer {\n\treturn &buffer{b, 0}\n}\n\n// DecodeVarint wraps the actual method and updates the position\nfunc (b *buffer) DecodeVarint() (uint64, error) {\n\tv, n := protowire.ConsumeVarint(b.buf[b.position:])\n\tif n < 0 {\n\t\treturn 0, errors.Wrap(protowire.ParseError(n), \"error decoding varint with proto.Buffer\")\n\t}\n\tb.position += n\n\treturn v, nil\n}\n\n// DecodeRawBytes wraps the actual method and updates the position\nfunc (b *buffer) DecodeRawBytes(alloc bool) ([]byte, error) {\n\tv, n := protowire.ConsumeBytes(b.buf[b.position:])\n\tif n < 0 {\n\t\treturn nil, errors.Wrap(protowire.ParseError(n), \"error decoding raw bytes with proto.Buffer\")\n\t}\n\tb.position += n\n\tif alloc {\n\t\tv = append([]byte(nil), v...)\n\t}\n\treturn v, nil\n}\n\n// GetBytesConsumed returns the offset of the current position in the underlying []byte\nfunc (b *buffer) GetBytesConsumed() int {\n\treturn b.position\n}\n","sourceCodeStart":22,"sourceCodeEnd":53,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/ledger/blkstorage/protobuf_util.go#L22-L53","documentation":"DecodeRawBytes on the blkstorage buffer wrapper consumes a length-delimited field via protowire.ConsumeBytes; if the length prefix or remaining bytes are invalid (truncated record, negative length, malformed wire data) the parse error is wrapped as \"error decoding raw bytes with proto.Buffer\". It is the companion to DecodeVarint for reading nested protobuf fields of stored blocks.","triggerScenarios":"extractHeader, extractData, extractMetadata, or TestBuffer reading bytes where a length-delimited field's length exceeds the remaining buffer — i.e. truncated or corrupted block records, wrong offset into the file, or bytes not produced by the protobuf encoder.","commonSituations":"Block file truncated by crash/power loss mid-write, ledger copied while the peer was running, disk corruption, restoring mismatched blockfile/integrity-check files, or passing arbitrary (non-protobuf) byte slices to the helpers.","solutions":["Locate the corrupt record (block number/offset from the caller) and validate the block file; use the ledger's rollback-to-genesis or snapshot restore to recover.","Re-sync the ledger from other peers or the orderer after resetting the affected channel's ledger data.","If generating bytes programmatically, ensure you emit a complete length-delimited protobuf field before decoding."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if len(buf) == 0 {\n    return errors.New(\"empty block bytes\")\n}\nif _, n := protowire.ConsumeBytes(buf); n < 0 {\n    return fmt.Errorf(\"length-delimited field invalid: %v\", protowire.ParseError(n))\n}","typeGuard":null,"tryCatchPattern":"raw, err := b.DecodeRawBytes(true)\nif err != nil {\n    return fmt.Errorf(\"failed reading nested field at offset %d: %w\", b.position, err)\n}","preventionTips":["Never truncate or hand-edit block files; recover only via supported rollback/restore commands.","Snapshot ledgers while the peer is offline.","Keep blockfile and index files consistent — restore from the same backup generation.","Detect truncation early by comparing file sizes against recorded end offsets."],"tags":["protobuf","corruption","ledger"],"backgroundTag":"protobuf-decode-failure","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}