charmbracelet/crush · error

cannot get ownership: %w

Error message

cannot get ownership: %w

What it means

traverseUp determines the owner of the starting directory via fsext.Owner so subsequent probes can enforce ownership boundaries. This error wraps any failure of Owner(dir), typically a stat failure on the starting directory.

Source

Thrown at internal/fsext/lookup.go:171

	if err != nil {
		return nil, err
	}

	return found, nil
}

// traverseUp walks up from given directory up until filesystem root reached.
// It passes absolute path of current directory and staring directory owner ID
// to callback function. It is up to user to check ownership.
func traverseUp(dir string, walkFn func(dir string, owner int) error) error {
	cwd, err := filepath.Abs(dir)
	if err != nil {
		return fmt.Errorf("cannot convert CWD to absolute path: %w", err)
	}

	owner, err := Owner(dir)
	if err != nil {
		return fmt.Errorf("cannot get ownership: %w", err)
	}

	for {
		err := walkFn(cwd, owner)
		if err == nil || errors.Is(err, filepath.SkipDir) {
			parent := filepath.Dir(cwd)
			if parent == cwd {
				return nil
			}

			cwd = parent
			continue
		}

		if errors.Is(err, filepath.SkipAll) {
			return nil
		}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Verify dir exists and is accessible: run `stat <dir>` as the same user
  2. Correct the path (it may have been renamed/deleted) or recreate the directory
  3. Fix ownership/permissions so the running user can stat the directory
  4. If the directory may not exist, check os.Stat first and handle it explicitly rather than relying on the wrapped error

Example fix

// before
found, _ := fsext.LookupClosest(projectDir, ".crush.json")
// after
if _, err := os.Stat(projectDir); err != nil {
    return fmt.Errorf("project dir %s unavailable: %w", projectDir, err)
}
found, _ := fsext.LookupClosest(projectDir, ".crush.json")
Defensive patterns

Strategy: validation

Validate before calling

if fi, err := os.Stat(dir); err != nil {
    return fmt.Errorf("cannot read starting dir %s: %w", dir, err)
} else if !fi.IsDir() {
    return fmt.Errorf("%s is not a directory", dir)
}

Type guard

func statableDir(dir string) bool {
    fi, err := os.Stat(dir)
    return err == nil && fi.IsDir()
}

Try / catch

found, err := fsext.Lookup(dir, targets...)
if err != nil {
    if strings.Contains(err.Error(), "cannot get ownership") {
        // ownership unavailable — decide whether to proceed without boundary checks
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Calling Lookup/LookupClosest with a dir that cannot be stat'ed: the directory does not exist, the caller lacks permission on it, it was deleted concurrently, or it sits on a failed mount.

Common situations: Passing a project path that was renamed or removed; running with a user lacking search permission on the path (e.g. strict home directory perms); dangling paths on automounted volumes.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/695bb15de479f815. Report an issue: GitHub.