etcd-io/etcd · error
lease ID must be 8-byte
Error message
lease ID must be 8-byte
What it means
etcd-dump-db decodes records in the 'lease' bucket by converting each bbolt key to an int64 lease ID, which etcd always serializes as exactly 8 big-endian bytes. bytesToLeaseID panics when the key length differs, meaning the tool encountered a record in the lease bucket that is not a lease key — i.e. the data dir's layout does not match what this tool version expects, or the bucket content is corrupted.
Source
Thrown at tools/etcd-dump-db/backend.go:83
"meta": metaDecoder,
}
func defaultDecoder(k, v []byte) {
fmt.Printf("key=%q, value=%q\n", k, v)
}
func keyDecoder(k, v []byte) {
rev := mvcc.BytesToBucketKey(k)
var kv mvccpb.KeyValue
if err := proto.Unmarshal(v, &kv); err != nil {
panic(err)
}
fmt.Printf("rev=%+v, value=[key %q | val %q | created %d | mod %d | ver %d]\n", rev, string(kv.Key), string(kv.Value), kv.CreateRevision, kv.ModRevision, kv.Version)
}
func bytesToLeaseID(bytes []byte) int64 {
if len(bytes) != 8 {
panic(fmt.Errorf("lease ID must be 8-byte"))
}
return int64(binary.BigEndian.Uint64(bytes))
}
func leaseDecoder(k, v []byte) {
leaseID := bytesToLeaseID(k)
var lpb leasepb.Lease
if err := proto.Unmarshal(v, &lpb); err != nil {
panic(err)
}
fmt.Printf("lease ID=%016x, TTL=%ds, remaining TTL=%ds\n", leaseID, lpb.TTL, lpb.RemainingTTL)
}
func authDecoder(k, v []byte) {
if string(k) == "authRevision" {
rev := binary.BigEndian.Uint64(v)
fmt.Printf("key=%q, value=%v\n", k, rev)
} else {View on GitHub (pinned to f744d457f4)
Solutions
- Rebuild/reinstall etcd-dump-db from the same etcd source tree and version as the server that produced the data dir (make build-tools from the matching tag).
- Double-check the --data-dir path points at the member's data dir (containing member/snap/db), not a parent or sibling directory.
- Validate the db before dumping: `etcdutl bbolt check <data-dir>/member/snap/db` to rule out corruption.
- If dumping another bucket was intended, use the iterate/dump subcommand without the lease decoder instead of iterate-leases.
Example fix
// before (tool built from wrong version, panics on lease bucket): // etcd-dump-db iterate-leases --data-dir /var/lib/etcd-wrong // after // git checkout v3.5.X && go install ./tools/etcd-dump-db // etcd-dump-db iterate-leases --data-dir /var/lib/etcd
Defensive patterns
Strategy: validation
Validate before calling
// Guard before decoding (if embedding the tool's logic):
func safeBytesToLeaseID(b []byte) (int64, bool) {
if len(b) != 8 {
return 0, false
}
return int64(binary.BigEndian.Uint64(b)), true
} Prevention
- Build etcd-dump-db from the same etcd release tag as the server that wrote the data dir.
- Point --data-dir at the member data dir containing member/snap/db.
- Run `etcdutl bbolt check` on the db before offline inspection.
- Prefer `etcd-dump-db list-bucket` first to confirm bucket layout matches expectations.
When it happens
Trigger: Running `etcd-dump-db iterate-leases --data-dir ...` (the command that routes keys through leaseDecoder) against a db whose lease bucket holds keys of a length other than 8; typically an etcd-dump-db binary built from a different release than the server that wrote the data dir.
Common situations: Using a stale tools/ checkout of etcd-dump-db against a data dir from a newer/older etcd; pointing --data-dir at the wrong subdirectory (e.g. member/wal leftover or a snap dir holding non-lease pages); a genuinely corrupted db file from an unclean shutdown.
Related errors
AI-assisted analysis of etcd-io/etcd@f744d457f4 (2026-08-15).
Data as JSON: /api/errors/dac91578686c8f46.
Report an issue: GitHub.