{"record":{"id":"ddedb93fa9fd0780","repo":"charmbracelet/crush","slug":"cannot-stat-s-w","errorCode":null,"errorMessage":"cannot stat %s: %w","messagePattern":"cannot stat (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/fsext/lookup.go","lineNumber":263,"sourceCode":"\t\treturn err\n\t}\n}\n\n// canonicalize resolves any symbolic links in path. If resolution fails\n// (typically because path does not exist yet) the original path is\n// returned cleaned, so callers can still perform stable equality checks.\nfunc canonicalize(path string) string {\n\tif resolved, err := filepath.EvalSymlinks(path); err == nil {\n\t\treturn resolved\n\t}\n\treturn filepath.Clean(path)\n}\n\n// probeEnt checks if entity at given path exists and belongs to given owner\nfunc probeEnt(fspath string, owner int) error {\n\t_, err := os.Stat(fspath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot stat %s: %w\", fspath, err)\n\t}\n\n\t// special case for ownership check bypass\n\tif owner == -1 {\n\t\treturn nil\n\t}\n\n\tfowner, err := Owner(fspath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot get ownership for %s: %w\", fspath, err)\n\t}\n\n\tif fowner != owner {\n\t\treturn os.ErrPermission\n\t}\n\n\treturn nil\n}","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/fsext/lookup.go#L245-L281","documentation":"probeEnt starts by stat-ing the candidate path to confirm it exists; any error is wrapped as \"cannot stat %s\". Callers (Lookup/LookupClosest variants) then filter os.ErrNotExist and os.ErrPermission, so this message normally surfaces only for unexpected stat failures, but it is also the internal carrier for ENOENT/EACCES.","triggerScenarios":"os.Stat on <dir>/<target> fails for any reason: file absent (ENOENT), permission denied (EACCES), path component is a file (ENOTDIR), symlink loop (ELOOP), or I/O error (EIO).","commonSituations":"Searching for config files (e.g. .crush.json) up a tree where some levels legitimately lack them — the ENOENT form is filtered upstream and harmless; EACCES on restrictive directories; ELOOP from `git worktree` + symlink tricks.","solutions":["If the wrapped error is os.ErrNotExist or os.ErrPermission, it is expected and already skipped — no action needed","For ENOTDIR, ensure no target-name component is a regular file in ancestors","Break symlink loops (ELOOP) and check mount health for EIO","Unwrap with errors.Is to branch on the specific errno in your own handling code"],"exampleFix":"// before\n_, err := fsext.Lookup(dir, target)\nif err != nil {\n    panic(err)\n}\n// after\n_, err := fsext.Lookup(dir, target)\nif err != nil {\n    if errors.Is(err, os.ErrNotExist) || errors.Is(err, os.ErrPermission) {\n        return nil // expected during upward lookup\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"// Check candidate exists before treating failure as unexpected\np := filepath.Join(dir, target)\nif _, err := os.Stat(p); err != nil {\n    if errors.Is(err, os.ErrNotExist) || errors.Is(err, os.ErrPermission) {\n        return nil // expected: lookup skips these\n    }\n}","typeGuard":"func probeErrIsBenign(err error) bool {\n    return errors.Is(err, os.ErrNotExist) || errors.Is(err, os.ErrPermission)\n}","tryCatchPattern":"_, err := fsext.Lookup(dir, targets...)\nif err != nil {\n    var pe *os.PathError\n    if errors.As(err, &pe) {\n        switch {\n        case errors.Is(pe.Err, syscall.ENOTDIR):\n            return handleComponentNotDir(pe.Path)\n        case errors.Is(pe.Err, syscall.ELOOP):\n            return handleSymlinkLoop(pe.Path)\n        }\n    }\n    return err\n}","preventionTips":["Remember ENOENT/EACCES are filtered internally — only unusual errnos reach you","errors.As with *os.PathError to recover path and errno","Break symlink loops in search trees","Don't shadow target names with regular files in ancestor dirs"],"tags":["filesystem","stat","lookup"],"backgroundTag":"stat-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}