lima-vm/lima · error
chown inode %d (%#q): %w
Error message
chown inode %d (%#q): %w
What it means
Thrown by pkg/apfs.Chown when chownInode locates the inode for a resolved path but refuses or fails to patch its owner/group. chownInode validates that the inode's current uid/gid equal the "noowners" placeholder IDs written by a no-ownership mount; a mismatch, a missing inode record, checksum failure, block write failure, or boundary/private_id validation error is wrapped here with the inode number and path.
Source
Thrown at pkg/apfs/chown.go:43
defer c.close()
vol, err := c.findVolume(volumeRole)
if err != nil {
return err
}
fsRootPhys, err := c.omapLookup(vol.omapTreeAddr, vol.rootTreeOID, vol.latestXID)
if err != nil {
return fmt.Errorf("resolving filesystem root tree OID %d: %w", vol.rootTreeOID, err)
}
for _, path := range paths {
inodeNum, err := c.resolvePath(fsRootPhys, vol.omapTreeAddr, vol.latestXID, path)
if err != nil {
return fmt.Errorf("resolving path %#q: %w", path, err)
}
if err := c.chownInode(fsRootPhys, vol.omapTreeAddr, vol.latestXID, inodeNum, uid, gid); err != nil {
return fmt.Errorf("chown inode %d (%#q): %w", inodeNum, path, err)
}
}
return nil
}
// container holds the open disk image file, the byte offset where
// the APFS container starts (nonzero for GPT-partitioned disks),
// and the APFS block size.
type container struct {
f *os.File
baseOffset int64 // byte offset of APFS container within file
blockSize uint32
}
// volumeInfo holds resolved volume information.
type volumeInfo struct {
omapTreeAddr uint64 // physical address of volume omap B-tree root
rootTreeOID uint64 // virtual OID of filesystem B-tree rootView on GitHub (pinned to dd909d0973)
Solutions
- Run Chown only once per image; verify current ownership state before re-running, or regenerate the image to restore the noowners placeholder state.
- Check the disk image file is writable (os.O_RDWR) and not opened by another process.
- Ensure the volume was created/mounted with ownership disabled (noowners) so inodes carry the placeholder IDs Chown expects.
- If the image is corrupted, rebuild or re-export it.
Example fix
// before
_ = apfs.Chown(disk, apfs.VolRoleData, 501, 20, paths...) // run in a retry loop; second run fails
// after
if err := apfs.Chown(disk, apfs.VolRoleData, 501, 20, paths...); err != nil {
log.Fatal(err) // do not retry: placeholder ownership is consumed by the first successful run
} Defensive patterns
Strategy: try-catch
Validate before calling
// run on an image in the pristine noowners state; skip if already chowned
if alreadyChowned[diskPath] {
return nil
} Try / catch
if err := apfs.Chown(disk, role, uid, gid, paths...); err != nil {
if strings.Contains(err.Error(), "expected") && strings.Contains(err.Error(), "noowners") {
// ownership placeholder already replaced: treat as success or rebuild image
return nil
}
return err
} Prevention
- Call Chown exactly once per image; make the operation idempotent at the caller level.
- Keep the image unmounted with ownership disabled (noowners) until after Chown.
- Ensure the image file is writable and not opened elsewhere during the patch.
When it happens
Trigger: Calling apfs.Chown on a volume whose target inode does not currently hold the noowners placeholder ownership (e.g. the volume was previously chowned, or was mounted WITH ownership honored), the inode record is absent from the filesystem B-tree, or the underlying writeBlock fails (read-only file, full disk, I/O error).
Common situations: Running Chown twice — the second run fails because the ownership no longer matches the placeholder; the image was mounted by macOS with owners enabled between operations; the disk image file lacks write permission; inode-record corruption after an unclean shutdown of the image.
Related errors
- resolving filesystem root tree OID %d: %w
- resolving path %#q: %w
- read block 0: %w
- finding APFS partition: %w
- reading container superblock: %w
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/bf902adab877ee5f.
Report an issue: GitHub.