lima-vm/lima · error

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

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.

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)

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.