dgraph-io/dgraph · critical
cannot unmarshal list part with key %s
Error message
cannot unmarshal list part with key %s
What it means
This error wraps a failure from unmarshalOrCopy when the bytes read for one part of a multi-part posting list cannot be decoded into pb.PostingList. It means the data on disk does not match the expected protobuf schema, i.e. the stored posting list part is corrupt or written by an incompatible version.
Source
Thrown at posting/list.go:2279
// readListPart reads one split of a posting list from Badger.
func (l *List) readListPart(startUid uint64) (*pb.PostingList, error) {
key, err := x.SplitKey(l.key, startUid)
if err != nil {
return nil, errors.Wrapf(err,
"cannot generate key for list with base key %s and start UID %d",
hex.EncodeToString(l.key), startUid)
}
txn := pstore.NewTransactionAt(l.minTs, false)
defer txn.Discard()
item, err := txn.Get(key)
if err != nil {
return nil, errors.Wrapf(err, "could not read list part with key %s",
hex.EncodeToString(key))
}
part := &pb.PostingList{}
if err := unmarshalOrCopy(part, item); err != nil {
return nil, errors.Wrapf(err, "cannot unmarshal list part with key %s",
hex.EncodeToString(key))
}
return part, nil
}
// shouldSplit returns true if the given plist should be split in two.
func shouldSplit(plist *pb.PostingList) bool {
return proto.Size(plist) >= maxListSize && len(plist.Pack.Blocks) > 1
}
func (out *rollupOutput) updateSplits() {
if out.plist == nil || len(out.parts) > 0 {
out.plist = &pb.PostingList{}
}
out.plist.Splits = out.splits()
}
func (out *rollupOutput) recursiveSplit() {View on GitHub (pinned to 759e242be6)
Solutions
- Restore the affected keys from a known-good backup
- Verify all nodes run the same Dgraph/badger version and codecs match
- Run badger's iterate/verify tooling to locate corrupt entries, then force re-index (drop all + re-bulk-load)
- Check protobuf schema compatibility if custom builds are involved
Defensive patterns
Strategy: fallback
Validate before calling
// Validate stored bytes decode before use
func partDecodable(item *badger.Item) bool {
var pl pb.PostingList
buf, err := item.ValueCopy(nil)
if err != nil { return false }
return proto.Unmarshal(buf, &pl) == nil
} Try / catch
part, err := readListPart(key, startUid)
if err != nil && strings.Contains(err.Error(), "cannot unmarshal list part") {
// treat as corrupt: quarantine key, alert, fall back to backup/rollup
markCorrupt(key)
return nil, err
} Prevention
- Pin cluster to one compatible Dgraph version; avoid mixed-version reads
- Take regular backups (dgraph backup) and verify restores
- Run badger verification after unclean shutdowns
- Test schema/protobuf compatibility before custom data migrations
When it happens
Trigger: unmarshalOrCopy(part, item) returns an error while decoding a posting-list part in readListPart — typically because the value bytes are truncated, corrupted, or produced by a different protobuf schema/version.
Common situations: Upgrading/downgrading Dgraph across incompatible versions; value-log corruption after crash; copy optimization reading across mismatched snapshot data; manual data migration between clusters.
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
- could not read list part with key %s
- cannot export data inside DB at %s
- while copying value
- cannot load schema after streaming data
- failed to open BadgerDB at [%v]: %v
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/edbf598dc9133b51.
Report an issue: GitHub.