{"record":{"id":"695bb15de479f815","repo":"charmbracelet/crush","slug":"cannot-get-ownership-w","errorCode":null,"errorMessage":"cannot get ownership: %w","messagePattern":"cannot get ownership: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/fsext/lookup.go","lineNumber":171,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn found, nil\n}\n\n// traverseUp walks up from given directory up until filesystem root reached.\n// It passes absolute path of current directory and staring directory owner ID\n// to callback function. It is up to user to check ownership.\nfunc traverseUp(dir string, walkFn func(dir string, owner int) error) error {\n\tcwd, err := filepath.Abs(dir)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot convert CWD to absolute path: %w\", err)\n\t}\n\n\towner, err := Owner(dir)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot get ownership: %w\", err)\n\t}\n\n\tfor {\n\t\terr := walkFn(cwd, owner)\n\t\tif err == nil || errors.Is(err, filepath.SkipDir) {\n\t\t\tparent := filepath.Dir(cwd)\n\t\t\tif parent == cwd {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tcwd = parent\n\t\t\tcontinue\n\t\t}\n\n\t\tif errors.Is(err, filepath.SkipAll) {\n\t\t\treturn nil\n\t\t}\n","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/fsext/lookup.go#L153-L189","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify dir exists and is accessible: run `stat <dir>` as the same user","Correct the path (it may have been renamed/deleted) or recreate the directory","Fix ownership/permissions so the running user can stat the directory","If the directory may not exist, check os.Stat first and handle it explicitly rather than relying on the wrapped error"],"exampleFix":"// before\nfound, _ := fsext.LookupClosest(projectDir, \".crush.json\")\n// after\nif _, err := os.Stat(projectDir); err != nil {\n    return fmt.Errorf(\"project dir %s unavailable: %w\", projectDir, err)\n}\nfound, _ := fsext.LookupClosest(projectDir, \".crush.json\")","handlingStrategy":"validation","validationCode":"if fi, err := os.Stat(dir); err != nil {\n    return fmt.Errorf(\"cannot read starting dir %s: %w\", dir, err)\n} else if !fi.IsDir() {\n    return fmt.Errorf(\"%s is not a directory\", dir)\n}","typeGuard":"func statableDir(dir string) bool {\n    fi, err := os.Stat(dir)\n    return err == nil && fi.IsDir()\n}","tryCatchPattern":"found, err := fsext.Lookup(dir, targets...)\nif err != nil {\n    if strings.Contains(err.Error(), \"cannot get ownership\") {\n        // ownership unavailable — decide whether to proceed without boundary checks\n        return nil\n    }\n    return err\n}","preventionTips":["Confirm the starting directory exists before lookups (projects can be moved/deleted)","Ensure the runtime user can traverse (x) the full path to dir","Avoid lookup roots on flaky automounts","Handle dir-unavailable as a normal condition, not a crash"],"tags":["filesystem","ownership","stat"],"backgroundTag":"ownership-check-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}