{"record":{"id":"bf902adab877ee5f","repo":"lima-vm/lima","slug":"chown-inode-d-q-w","errorCode":null,"errorMessage":"chown inode %d (%#q): %w","messagePattern":"chown inode (.+?) \\(%#q\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apfs/chown.go","lineNumber":43,"sourceCode":"\tdefer c.close()\n\n\tvol, err := c.findVolume(volumeRole)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfsRootPhys, err := c.omapLookup(vol.omapTreeAddr, vol.rootTreeOID, vol.latestXID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"resolving filesystem root tree OID %d: %w\", vol.rootTreeOID, err)\n\t}\n\n\tfor _, path := range paths {\n\t\tinodeNum, err := c.resolvePath(fsRootPhys, vol.omapTreeAddr, vol.latestXID, path)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"resolving path %#q: %w\", path, err)\n\t\t}\n\t\tif err := c.chownInode(fsRootPhys, vol.omapTreeAddr, vol.latestXID, inodeNum, uid, gid); err != nil {\n\t\t\treturn fmt.Errorf(\"chown inode %d (%#q): %w\", inodeNum, path, err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// container holds the open disk image file, the byte offset where\n// the APFS container starts (nonzero for GPT-partitioned disks),\n// and the APFS block size.\ntype container struct {\n\tf          *os.File\n\tbaseOffset int64 // byte offset of APFS container within file\n\tblockSize  uint32\n}\n\n// volumeInfo holds resolved volume information.\ntype volumeInfo struct {\n\tomapTreeAddr uint64 // physical address of volume omap B-tree root\n\trootTreeOID  uint64 // virtual OID of filesystem B-tree root","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/apfs/chown.go#L25-L61","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\n_ = apfs.Chown(disk, apfs.VolRoleData, 501, 20, paths...) // run in a retry loop; second run fails\n// after\nif err := apfs.Chown(disk, apfs.VolRoleData, 501, 20, paths...); err != nil {\n    log.Fatal(err) // do not retry: placeholder ownership is consumed by the first successful run\n}","handlingStrategy":"try-catch","validationCode":"// run on an image in the pristine noowners state; skip if already chowned\nif alreadyChowned[diskPath] {\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := apfs.Chown(disk, role, uid, gid, paths...); err != nil {\n    if strings.Contains(err.Error(), \"expected\") && strings.Contains(err.Error(), \"noowners\") {\n        // ownership placeholder already replaced: treat as success or rebuild image\n        return nil\n    }\n    return err\n}","preventionTips":["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."],"tags":["apfs","disk-image","ownership","write-failure"],"backgroundTag":"inode-ownership-mismatch","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}