lima-vm/lima · error

filesystem B-tree node: %w

Error message

filesystem B-tree node: %w

What it means

This error wraps a failure from verifyBTreeNodeType while walking the directory B-tree in lookupDirEntry. The block's checksum was valid, but the node's on-disk type/magic fields are not a valid B-tree node (wrong object type, unknown flags). It means the walk landed on a block that is not the expected kind of B-tree node.

Source

Thrown at pkg/apfs/chown.go:522

}

// 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 {
			valueAreaEnd -= btreeInfoSize
		}

View on GitHub (pinned to dd909d0973)

Solutions

  1. Verify you are passing the correct filesystem-tree root physical address and omap tree address
  2. Run fsck_apfs to check the container/volume structure
  3. Confirm the image was produced by a compatible APFS on-disk format version
  4. Re-create/restore the volume if the structure is genuinely damaged
Defensive patterns

Strategy: validation

Validate before calling

// Ensure you resolved fsRootPhys and omapTreeAddr from the same volume superblock
if fsRootVol != omapVol {
    return errors.New("fs tree and omap tree come from different volumes")
}

Type guard

func isBTreeNodeTypeError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "filesystem B-tree node:")
}

Try / catch

fileID, err := c.resolvePath(fsRootPhys, omapTreeAddr, maxXID, path)
if isBTreeNodeTypeError(err) {
    return fmt.Errorf("bad tree structure, re-resolve roots or fsck: %w", err)
}

Prevention

When it happens

Trigger: resolvePath/lookupDirEntry follows an omap or child pointer that resolves to a physical block containing non-B-tree data (e.g. an fs tree where a catalog/omap block was expected), or parsing a volume whose object type constants differ from what the code expects.

Common situations: Pointing the reader at the wrong volume superblock or omap root; reading a block from an APFS version with different node layout; an image where the referenced child OID maps to a data block instead of a tree node.

Related errors


AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01). Data as JSON: /api/errors/ac5a12e071ac2525. Report an issue: GitHub.