{"record":{"id":"6a508770b2c83ae2","repo":"lima-vm/lima","slug":"inode-d-has-ownership-d-d-expected-d-d-from","errorCode":null,"errorMessage":"inode %d has ownership %d:%d, expected %d:%d from noowners mount","messagePattern":"inode (.+?) has ownership (.+?):(.+?), expected (.+?):(.+?) from noowners mount","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/apfs/chown.go","lineNumber":689,"sourceCode":"\t\t\t\tif keyHeader != targetKeyHeader {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// Found the inode. Validate before writing.\n\t\t\t\tvalStart := valueAreaEnd - vOff\n\n\t\t\t\tif valStart+inodeGroupOff+4 > c.blockSize {\n\t\t\t\t\treturn fmt.Errorf(\"inode %d value exceeds block boundary\", inodeNum)\n\t\t\t\t}\n\n\t\t\t\tif privateID := le.Uint64(blk[valStart+inodePrivateIDOff:]); privateID != inodeNum {\n\t\t\t\t\treturn fmt.Errorf(\"inode %d has mismatched private_id %d\", inodeNum, privateID)\n\t\t\t\t}\n\n\t\t\t\tcurrentUID := le.Uint32(blk[valStart+inodeOwnerOff:])\n\t\t\t\tcurrentGID := le.Uint32(blk[valStart+inodeGroupOff:])\n\t\t\t\tif currentUID != noownersPlaceholderID || currentGID != noownersPlaceholderID {\n\t\t\t\t\treturn fmt.Errorf(\"inode %d has ownership %d:%d, expected %d:%d from noowners mount\",\n\t\t\t\t\t\tinodeNum, currentUID, currentGID, noownersPlaceholderID, noownersPlaceholderID)\n\t\t\t\t}\n\n\t\t\t\tle.PutUint32(blk[valStart+inodeOwnerOff:], uid)\n\t\t\t\tle.PutUint32(blk[valStart+inodeGroupOff:], gid)\n\t\t\t\tupdateChecksum(blk)\n\t\t\t\treturn c.writeBlock(blkAddr, blk)\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"inode %d not found in filesystem B-tree\", inodeNum)\n\t\t}\n\n\t\t// Internal node: descend.\n\t\tchildIdx := uint32(0)\n\t\tfor i := range nkeys {\n\t\t\tkOff, _ := c.readTocEntry(blk, tocStart, i, isFixedKV)\n\t\t\tkeyStart := keyAreaStart + kOff\n\t\t\tkeyHeader := le.Uint64(blk[keyStart:])\n","sourceCodeStart":671,"sourceCodeEnd":707,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/apfs/chown.go#L671-L707","documentation":"chownInode only rewrites ownership when the inode currently holds the noowners placeholder uid/gid (as set on a noowners mount); if the stored ownership differs from that placeholder, it aborts. This is a safety guard: the tool only takes ownership of files that the noowners mount left with the placeholder, never files with real ownership.","triggerScenarios":"Calling the ownership-repair path on a volume where the target inode already has real uid/gid values — the volume was mounted without the noowners flag, ownership was already repaired once, or the file was created with real ownership rather than the placeholder.","commonSituations":"Running the repair twice; mounting the volume normally (owners enforced) instead of with noowners; files whose ownership was set by the guest OS after mount.","solutions":["Remount/mount the volume with the noowners option so inodes get the placeholder ownership, then retry","If the current ownership is already correct, skip the repair — no action needed","Verify you are targeting the right inode/volume; a legitimate owner may already be set","Only bypass this guard if you fully control the image and accept rewriting arbitrary ownership"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check: only run the repair when the volume was mounted with noowners\nif !volumeMountedNoowners(volumeID) {\n    return fmt.Errorf(\"volume %s not mounted noowners; ownership will not be placeholder\", volumeID)\n}","typeGuard":"func isOwnershipNotPlaceholder(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"expected\") && strings.Contains(err.Error(), \"noowners mount\")\n}","tryCatchPattern":"if err := c.chownInode(root, omap, maxXID, ino, uid, gid); isOwnershipNotPlaceholder(err) {\n    // already owned: treat as no-op success or remount with noowners and retry\n    return nil\n}","preventionTips":["Mount volumes with the noowners option before running the repair","Make the repair idempotent: skip inodes that already have final ownership","Run the repair exactly once per mount cycle"],"tags":["apfs","inode","ownership","noowners","chown"],"backgroundTag":"inode-ownership-not-placeholder","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}