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
- Re-resolve the path with resolvePath against the same volume/tree immediately before chownInode
- Verify the inode number exists (e.g. via fsck or by listing directory entries)
- Ensure fsRootPhys/omapTreeAddr/maxXID are consistent between lookup and chown
- 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
- Always resolve and chown against the same volume/snapshot/maxXID
- Do not cache inode numbers across tree mutations
- Treat not-found as an expected outcome and skip gracefully
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
- directory entry %#q not found
- inode %d value exceeds block boundary
- inode %d has mismatched private_id %d
- inode %d has ownership %d:%d, expected %d:%d from noowners m
- filesystem B-tree node checksum failed
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/71cae355219126e6.
Report an issue: GitHub.