lima-vm/lima · error

inode %d not found in filesystem B-tree

Error message

inode %d not found in filesystem B-tree

What it means

chownInode walked the inode B-tree to a leaf and scanned all keys for the target inode number's key header without finding a match. The tree is healthy; the requested inode simply has no record in this filesystem B-tree.

Source

Thrown at pkg/apfs/chown.go:698

				}

				if privateID := le.Uint64(blk[valStart+inodePrivateIDOff:]); privateID != inodeNum {
					return fmt.Errorf("inode %d has mismatched private_id %d", inodeNum, privateID)
				}

				currentUID := le.Uint32(blk[valStart+inodeOwnerOff:])
				currentGID := le.Uint32(blk[valStart+inodeGroupOff:])
				if currentUID != noownersPlaceholderID || currentGID != noownersPlaceholderID {
					return fmt.Errorf("inode %d has ownership %d:%d, expected %d:%d from noowners mount",
						inodeNum, currentUID, currentGID, noownersPlaceholderID, noownersPlaceholderID)
				}

				le.PutUint32(blk[valStart+inodeOwnerOff:], uid)
				le.PutUint32(blk[valStart+inodeGroupOff:], gid)
				updateChecksum(blk)
				return c.writeBlock(blkAddr, blk)
			}
			return fmt.Errorf("inode %d not found in filesystem B-tree", inodeNum)
		}

		// Internal node: descend.
		childIdx := uint32(0)
		for i := range nkeys {
			kOff, _ := c.readTocEntry(blk, tocStart, i, isFixedKV)
			keyStart := keyAreaStart + kOff
			keyHeader := le.Uint64(blk[keyStart:])

			if compareFSKeyHeader(keyHeader, targetKeyHeader) <= 0 {
				childIdx = i
			} else {
				break
			}
		}

		_, vOff := c.readTocEntry(blk, tocStart, childIdx, isFixedKV)
		childOID := le.Uint64(blk[valueAreaEnd-vOff:])

View on GitHub (pinned to dd909d0973)

Solutions

  1. Re-resolve the path with resolvePath against the same volume/tree immediately before chownInode
  2. Verify the inode number exists (e.g. via fsck or by listing directory entries)
  3. Ensure fsRootPhys/omapTreeAddr/maxXID are consistent between lookup and chown
  4. Treat as a clean not-found and skip the inode rather than retrying
Defensive patterns

Strategy: try-catch

Validate before calling

// Re-resolve immediately before chown with identical tree parameters
ino, err := c.resolvePath(fsRoot, omap, maxXID, path)
if err != nil {
    return err
}
_ = c.chownInode(fsRoot, omap, maxXID, ino, uid, gid)

Type guard

func isInodeNotFound(err error) bool {
    return err != nil && strings.Contains(err.Error(), "not found in filesystem B-tree")
}

Try / catch

if err := c.chownInode(root, omap, maxXID, ino, uid, gid); isInodeNotFound(err) {
    return fmt.Errorf("inode %d vanished; re-resolve path: %w", ino, err)
}

Prevention

When it happens

Trigger: Calling chownInode with an inode number that does not exist in the volume — a stale inode number from a deleted file, an inode from a different volume/snapshot, or a wrong file_id obtained from an earlier directory lookup against a different tree.

Common situations: Resolving a path in one snapshot and chowning in another; inode recycled after deletion; targeting a volume where the path resolved to a different file.

Related errors


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