lima-vm/lima · error
expected B-tree node type (2 or 3), got %#x
Error message
expected B-tree node type (2 or 3), got %#x
What it means
verifyBTreeNodeType validates that a block's object type field (masked) is OBJECT_TYPE_BTREE (0x02) or OBJECT_TYPE_BTREE_NODE (0x03). This is the root cause message wrapped by callers as 'omap node: %w' or 'filesystem B-tree node: %w'. It indicates the parser followed a pointer to a block that is not a B-tree node, i.e. on-disk structure differs from what the parser expects.
Source
Thrown at pkg/apfs/chown.go:397
// For fixed-KV nodes (kvoff_t): 4 bytes per entry (k_off u16, v_off u16).
// For variable-KV nodes (kvloc_t): 8 bytes per entry (k.off u16, k.len u16, v.off u16, v.len u16).
// Returns keyOffset and valueOffset (both relative to their respective areas).
func (c *container) readTocEntry(blk []byte, tocStart, index uint32, fixedKV bool) (keyOff, valOff uint32) {
if fixedKV {
off := tocStart + index*4
return uint32(le.Uint16(blk[off:])), uint32(le.Uint16(blk[off+2:]))
}
off := tocStart + index*8
return uint32(le.Uint16(blk[off:])), uint32(le.Uint16(blk[off+4:]))
}
// verifyBTreeNodeType checks that a block's object type indicates a
// B-tree node: OBJECT_TYPE_BTREE (0x02, root) or OBJECT_TYPE_BTREE_NODE
// (0x03, non-root).
func verifyBTreeNodeType(blk []byte) error {
oType := le.Uint32(blk[objTypeOff:]) & objTypeMask
if oType != 0x02 && oType != 0x03 {
return fmt.Errorf("expected B-tree node type (2 or 3), got %#x", oType)
}
return nil
}
func compareOmapKey(oid1, xid1, oid2, xid2 uint64) int {
if oid1 < oid2 {
return -1
}
if oid1 > oid2 {
return 1
}
if xid1 < xid2 {
return -1
}
if xid1 > xid2 {
return 1
}
return 0View on GitHub (pinned to dd909d0973)
Solutions
- Confirm the APFS container's block size (parser assumes standard offsets; test with a 4096-byte-block image).
- Run fsck_apfs from a macOS host and retry on the repaired image.
- Re-copy the image from a cleanly shut-down VM to rule out corruption.
- Check whether the image comes from a macOS version with on-disk format changes unsupported by this parser.
- Verify you are not reading the wrong region (e.g. non-APFS partition) as a B-tree.
Defensive patterns
Strategy: type-guard
Validate before calling
// Pre-flight: ensure the image is a raw APFS container with a plausible block size.
info, err := os.Stat(diskPath)
if err != nil { return err }
if info.Size() == 0 || info.Size()%4096 != 0 {
return errors.New("image size is not block-aligned; wrong file format?")
} Try / catch
if err := apfs.Chown(diskPath, role, uid, gid, paths...); err != nil {
if strings.Contains(err.Error(), "expected B-tree node type") {
return fmt.Errorf("unsupported or corrupt APFS layout in %s: %w", diskPath, err)
}
return err
} Prevention
- Use raw APFS images with standard 4KiB blocks.
- Pin guest macOS versions to ones the parser was tested with.
- Repair images with fsck_apfs before editing.
- Guard against concurrent modification of the image file.
When it happens
Trigger: Following a corrupt child pointer, applying fixed offsets to an image with an unexpected block size, or parsing an APFS variant/newer format where the type constants or layout differ.
Common situations: Very new or unusual macOS images, wrong disk image (non-APFS region interpreted as a tree), corrupted metadata, or parser constant mismatches with large block-size (8K/16K) containers.
Related errors
- omap node: %w
- reading omap child node: %w
- filesystem B-tree node: %w
- disk format %#q not supported, use `qcow2` or `raw` instead
- the YAML is invalid, attempted to save the buffer as %#q but
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/ec0061b414877ce3.
Report an issue: GitHub.