{"record":{"id":"ec0061b414877ce3","repo":"lima-vm/lima","slug":"expected-b-tree-node-type-2-or-3-got-x","errorCode":null,"errorMessage":"expected B-tree node type (2 or 3), got %#x","messagePattern":"expected B-tree node type \\(2 or 3\\), got %#x","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apfs/chown.go","lineNumber":397,"sourceCode":"// For fixed-KV nodes (kvoff_t): 4 bytes per entry (k_off u16, v_off u16).\n// For variable-KV nodes (kvloc_t): 8 bytes per entry (k.off u16, k.len u16, v.off u16, v.len u16).\n// Returns keyOffset and valueOffset (both relative to their respective areas).\nfunc (c *container) readTocEntry(blk []byte, tocStart, index uint32, fixedKV bool) (keyOff, valOff uint32) {\n\tif fixedKV {\n\t\toff := tocStart + index*4\n\t\treturn uint32(le.Uint16(blk[off:])), uint32(le.Uint16(blk[off+2:]))\n\t}\n\toff := tocStart + index*8\n\treturn uint32(le.Uint16(blk[off:])), uint32(le.Uint16(blk[off+4:]))\n}\n\n// verifyBTreeNodeType checks that a block's object type indicates a\n// B-tree node: OBJECT_TYPE_BTREE (0x02, root) or OBJECT_TYPE_BTREE_NODE\n// (0x03, non-root).\nfunc verifyBTreeNodeType(blk []byte) error {\n\toType := le.Uint32(blk[objTypeOff:]) & objTypeMask\n\tif oType != 0x02 && oType != 0x03 {\n\t\treturn fmt.Errorf(\"expected B-tree node type (2 or 3), got %#x\", oType)\n\t}\n\treturn nil\n}\n\nfunc compareOmapKey(oid1, xid1, oid2, xid2 uint64) int {\n\tif oid1 < oid2 {\n\t\treturn -1\n\t}\n\tif oid1 > oid2 {\n\t\treturn 1\n\t}\n\tif xid1 < xid2 {\n\t\treturn -1\n\t}\n\tif xid1 > xid2 {\n\t\treturn 1\n\t}\n\treturn 0","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/apfs/chown.go#L379-L415","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// Pre-flight: ensure the image is a raw APFS container with a plausible block size.\ninfo, err := os.Stat(diskPath)\nif err != nil { return err }\nif info.Size() == 0 || info.Size()%4096 != 0 {\n\treturn errors.New(\"image size is not block-aligned; wrong file format?\")\n}","typeGuard":null,"tryCatchPattern":"if err := apfs.Chown(diskPath, role, uid, gid, paths...); err != nil {\n\tif strings.Contains(err.Error(), \"expected B-tree node type\") {\n\t\treturn fmt.Errorf(\"unsupported or corrupt APFS layout in %s: %w\", diskPath, err)\n\t}\n\treturn err\n}","preventionTips":["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."],"tags":["apfs","btree","validation"],"backgroundTag":"btree-node-type-invalid","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}