{"record":{"id":"a9489605451bd0a7","repo":"lima-vm/lima","slug":"inode-d-has-mismatched-private-id-d","errorCode":null,"errorMessage":"inode %d has mismatched private_id %d","messagePattern":"inode (.+?) has mismatched private_id (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apfs/chown.go","lineNumber":683,"sourceCode":"\t\tif isLeaf {\n\t\t\tfor i := range nkeys {\n\t\t\t\tkOff, vOff := c.readTocEntry(blk, tocStart, i, isFixedKV)\n\t\t\t\tkeyStart := keyAreaStart + kOff\n\t\t\t\tkeyHeader := le.Uint64(blk[keyStart:])\n\n\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.","sourceCodeStart":665,"sourceCodeEnd":701,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/apfs/chown.go#L665-L701","documentation":"chownInode found an inode record whose private_id field does not equal the inode number being targeted. In APFS the inode value's private_id must match its key's inode number; a mismatch means the located value is not actually this inode (or the record is corrupt), so the write is refused to avoid chowning the wrong record.","triggerScenarios":"The B-tree lookup matched a key header for inodeNum but the value at that offset belongs to a different object (corruption, wrong offset constants like inodePrivateIDOff, or toc/value offset desync), or the image was modified by another tool between reads.","commonSituations":"Images altered by third-party APFS tools; constants drifted for a newer on-disk format; corruption that still passes checksum because the wrong block was cached.","solutions":["Run fsck_apfs to validate inode records","Confirm the offset constants (inodePrivateIDOff, value area math) match the image's on-disk format","Re-read the tree from the current volume superblock to drop any stale cached block","Do not force the write — chowning a mismatched record would corrupt the filesystem"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// Only target inodes known to carry the noowners placeholder\nif !inodeIsOwnedByNoownersMount(volumeID, inodeNum) {\n    return fmt.Errorf(\"inode %d not in noowners state; remount with noowners\", inodeNum)\n}","typeGuard":"func isPrivateIDMismatch(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"mismatched private_id\")\n}","tryCatchPattern":"if err := c.chownInode(root, omap, maxXID, ino, uid, gid); isPrivateIDMismatch(err) {\n    return fmt.Errorf(\"refusing write: record is not this inode; fsck required: %w\", err)\n}","preventionTips":["Never bypass the private_id check; it protects against chowning the wrong record","Re-read blocks freshly instead of reusing caches across external modifications","Verify offset constants against the image's on-disk format version"],"tags":["apfs","inode","private-id","integrity","chown"],"backgroundTag":"inode-private-id-mismatch","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}