lima-vm/lima · critical
filesystem B-tree node checksum failed
Error message
filesystem B-tree node checksum failed
What it means
This error is thrown by lookupDirEntry when the on-disk checksum (fletcher/CRC) of an APFS B-tree node block read during a directory-entry lookup does not match. The library verifies every B-tree node it touches before parsing it, because a corrupt node would produce garbage directory entries. It indicates block-level corruption of the filesystem tree being walked, not a caller mistake.
Source
Thrown at pkg/apfs/chown.go:519
cnid = fileID
}
return cnid, nil
}
// lookupDirEntry searches the filesystem B-tree for a directory record
// matching parentCNID and name, returning the file_id from j_drec_val_t.
func (c *container) lookupDirEntry(fsRootPhys, omapTreeAddr, maxXID, parentCNID uint64, name string) (uint64, error) {
targetKeyHeader := (uint64(apfsTypeDirRec) << objTypeShift) | (parentCNID & objIDMask)
targetHash := drecNameHash(name)
blk, err := c.readBlock(fsRootPhys)
if err != nil {
return 0, err
}
for {
if verifyChecksum(blk) != nil {
return 0, errors.New("filesystem B-tree node checksum failed")
}
if err := verifyBTreeNodeType(blk); err != nil {
return 0, fmt.Errorf("filesystem B-tree node: %w", err)
}
flags := le.Uint16(blk[btnFlagsOff:])
nkeys := le.Uint32(blk[btnNKeysOff:])
tspOff := le.Uint16(blk[btnTableSpaceOff:])
tspLen := le.Uint16(blk[btnTableSpaceOff+2:])
tocStart := btnDataOff + uint32(tspOff)
keyAreaStart := tocStart + uint32(tspLen)
isLeaf := flags&btnodeLeaf != 0
isFixedKV := flags&btnodeFixedKVSize != 0
isRoot := flags&btnodeRoot != 0
valueAreaEnd := c.blockSize
if isRoot {View on GitHub (pinned to dd909d0973)
Solutions
- Run fsck_apfs on the volume/image to detect and repair the corrupt B-tree node
- Restore the disk image or volume from a backup/snapshot taken before the corruption
- Verify the image file is not truncated and its size matches the APFS container description
- Re-run the lookup with the correct max XID / omap tree so current, not stale, blocks are resolved
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify image integrity before walking
if fi, err := os.Stat(imagePath); err != nil || fi.Size() < expectedMinSize {
return fmt.Errorf("image %s missing or truncated", imagePath)
} Type guard
func isBTreeChecksumFailure(err error) bool {
return err != nil && strings.Contains(err.Error(), "B-tree node checksum failed")
} Try / catch
inode, err := c.resolvePath(root, omap, maxXID, path)
if isBTreeChecksumFailure(err) {
// block-level corruption: surface as fatal, suggest fsck_apfs
return fmt.Errorf("volume corrupt, run fsck_apfs: %w", err)
} Prevention
- Always copy disk images while the source VM is shut down
- Keep checksums/verified backups of images before operating on them
- Run fsck_apfs before read-modify-write operations on an image
- Use storage that reports sector errors; monitor disk health
When it happens
Trigger: Calling resolvePath (which calls lookupDirEntry) on a volume whose directory B-tree blocks were corrupted on disk: partial/interrupted write, bit rot, bad disk sector, or reading a stale/mismatched physical block address after the tree was rebalanced or the snapshot changed under the reader.
Common situations: Reading an APFS disk image that was truncated or copied while the host was writing; inspecting a snapshot after the underlying disk developed bad sectors; mounting with a wrong omap/XID so a stale block (old checksum context) is read.
Related errors
- omap node checksum failed
- filesystem B-tree node: %w
- read block 0: %w
- reading container superblock: %w
- reading volume omap: %w
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/a0e59012bb74f5aa.
Report an issue: GitHub.