lima-vm/lima · error

looking up %#q in directory

Error message

looking up %#q in directory (cnid %d): %w

What it means

resolvePath walks each path component of a Chown target from the volume root, calling lookupDirEntry for each name against the current directory CNID. This error wraps any per-component failure — most commonly 'directory entry "name" not found', but also checksum/type failures or child OID resolution errors inside the filesystem B-tree. The message includes the component name and the parent CNID to pinpoint where the walk stopped.

Solutions

  1. Verify each path component exists on the target volume (mount the image read-only or inspect on a macOS host).
  2. Confirm you targeted the correct volumeRole — the path is resolved from that volume's root.
  3. Remember paths are relative to the volume root; strip the mount-point prefix (e.g. use 'Library/...' not 'System/Volumes/Data/Library/...').
  4. Check name case/spelling and that no intermediate component is a file.
  5. Run fsck_apfs if you suspect directory B-tree corruption.

Example fix

// before
err := apfs.Chown(disk, apfs.VolRoleData, uid, gid, "System/Volumes/Data/Library/LaunchDaemons/x.plist")
// after
err := apfs.Chown(disk, apfs.VolRoleData, uid, gid, "Library/LaunchDaemons/x.plist")
Defensive patterns

Strategy: validation

Validate before calling

func sanitizeChownPath(p string) error {
	p = strings.TrimPrefix(p, "/")
	if p == "" || strings.Contains(p, "..") {
		return fmt.Errorf("invalid chown path %q", p)
	}
	return nil
}

Try / catch

if err := apfs.Chown(diskPath, role, uid, gid, paths...); err != nil {
	var msg string
	if strings.Contains(err.Error(), "looking up ") && strings.Contains(err.Error(), "not found") {
		return fmt.Errorf("a path component does not exist on the target volume; check spelling and volumeRole: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling apfs.Chown with a path containing a component that does not exist in the target volume, a typo or wrong case (lookup is case-insensitive only via hash, exact otherwise), a component being a file rather than a directory, or metadata corruption along the B-tree path.

Common situations: Path typos in automation scripts, targeting files that exist on the system volume but not the data volume (or vice versa), paths relative to the volume root that need a different prefix, or images where the file was removed before the image was taken.

Related errors


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

Appendix: source

Thrown at pkg/apfs/chown.go:499

	}
	// Non-hashed key: compare names directly.
	entryName := c.readDrecName(blk, keyStart+8)
	return strings.Compare(entryName, targetName)
}

// resolvePath walks path components from the volume root, returning
// the inode number of the final path element.
func (c *container) resolvePath(fsRootPhys, omapTreeAddr, maxXID uint64, path string) (uint64, error) {
	parts := strings.Split(strings.Trim(path, "/"), "/")
	cnid := uint64(rootDirInodeNum)

	for _, name := range parts {
		if name == "" {
			continue
		}
		fileID, err := c.lookupDirEntry(fsRootPhys, omapTreeAddr, maxXID, cnid, name)
		if err != nil {
			return 0, fmt.Errorf("looking up %#q in directory (cnid %d): %w", name, cnid, err)
		}
		cnid = fileID
	}
	return cnid, nil
}

// lookupDirEntry searches the filesystem B-tree for a directory record
// matching parentCNID and name, returning the file_id from j_drec_val_t.
func (c *container) lookupDirEntry(fsRootPhys, omapTreeAddr, maxXID, parentCNID uint64, name string) (uint64, error) {
	targetKeyHeader := (uint64(apfsTypeDirRec) << objTypeShift) | (parentCNID & objIDMask)
	targetHash := drecNameHash(name)

	blk, err := c.readBlock(fsRootPhys)
	if err != nil {
		return 0, err
	}

	for {

View on GitHub (pinned to dd909d0973)