lima-vm/lima · error

omap entry for OID %d not found

Error message

omap entry for OID %d not found

What it means

omapLookup searched the omap leaf node for an entry whose key is (oid, xid <= maxXID) and found none. The omap maps virtual object IDs to physical addresses; if the requested virtual OID has no mapping at or below the given transaction ID, its physical address cannot be resolved. In findVolume unresolvable volumes are skipped silently; via lookupDirEntry/chownInode the error propagates wrapped as 'resolving child OID N'.

Source

Thrown at pkg/apfs/chown.go:346

			for i := range nkeys {
				kOff, vOff := c.readTocEntry(blk, tocStart, i, isFixedKV)
				keyStart := keyAreaStart + kOff
				entryOID := le.Uint64(blk[keyStart:])
				entryXID := le.Uint64(blk[keyStart+8:])

				if entryOID == oid && entryXID <= maxXID {
					// Value: ov_flags(4) + ov_size(4) + ov_paddr(8).
					valStart := valueAreaEnd - vOff
					physAddr := le.Uint64(blk[valStart+8:])
					if !found || entryXID > bestXID {
						bestPhysAddr = physAddr
						bestXID = entryXID
						found = true
					}
				}
			}
			if !found {
				return 0, fmt.Errorf("omap entry for OID %d not found", oid)
			}
			return bestPhysAddr, nil
		}

		// Internal node: find the last key <= (oid, maxXID) and descend.
		childIdx := uint32(0)
		for i := range nkeys {
			kOff, _ := c.readTocEntry(blk, tocStart, i, isFixedKV)
			keyStart := keyAreaStart + kOff
			entryOID := le.Uint64(blk[keyStart:])
			entryXID := le.Uint64(blk[keyStart+8:])

			cmp := compareOmapKey(entryOID, entryXID, oid, maxXID)
			if cmp <= 0 {
				childIdx = i
			} else {
				break
			}

View on GitHub (pinned to dd909d0973)

Solutions

  1. Ensure the maxXID passed is the latest XID from the corresponding superblock (findVolume already uses vol.latestXID; check custom code paths).
  2. Re-take the image from a clean shutdown so omap entries are consistent.
  3. Run fsck_apfs on the image to rebuild omap consistency.
  4. Avoid purging snapshots/trimming the image before running Chown.
  5. If the OID belongs to a different volume, resolve it through that volume's omap instead.
Defensive patterns

Strategy: retry

Try / catch

if err := apfs.Chown(diskPath, role, uid, gid, paths...); err != nil {
	if strings.Contains(err.Error(), "omap entry for OID") {
		// retry with a freshly-taken image; stale XIDs/purged OIDs do not recover in place
		return fmt.Errorf("virtual OID unresolvable; retake the image from a clean shutdown: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Resolving a virtual OID that was deleted (purged by a snapshot/trim), passing a maxXID lower than any entry's xid for that OID (e.g. using a stale containerXID while the volume tree was rewritten), or a corrupt leaf search path.

Common situations: Images with purged snapshots, using a stale XID captured from an older superblock while newer transactions exist, or referencing OIDs from a different volume's omap.

Related errors


AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01). Data as JSON: /api/errors/1ba96fcba9047ecb. Report an issue: GitHub.