{"record":{"id":"c4f0ea111d8a2901","repo":"charmbracelet/crush","slug":"error-accessing-file-w","errorCode":null,"errorMessage":"error accessing file: %w","messagePattern":"error accessing file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/tools/view.go","lineNumber":186,"sourceCode":"\t\t\t\t\t\tfor _, entry := range dirEntries {\n\t\t\t\t\t\t\tif strings.Contains(strings.ToLower(entry.Name()), strings.ToLower(base)) ||\n\t\t\t\t\t\t\t\tstrings.Contains(strings.ToLower(base), strings.ToLower(entry.Name())) {\n\t\t\t\t\t\t\t\tsuggestions = append(suggestions, filepath.Join(dir, entry.Name()))\n\t\t\t\t\t\t\t\tif len(suggestions) >= 3 {\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif len(suggestions) > 0 {\n\t\t\t\t\t\t\treturn fantasy.NewTextErrorResponse(fmt.Sprintf(\"File not found: %s\\n\\nDid you mean one of these?\\n%s\",\n\t\t\t\t\t\t\t\tfilePath, strings.Join(suggestions, \"\\n\"))), nil\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn fantasy.NewTextErrorResponse(fmt.Sprintf(\"File not found: %s\", filePath)), nil\n\t\t\t\t}\n\t\t\t\treturn fantasy.ToolResponse{}, fmt.Errorf(\"error accessing file: %w\", err)\n\t\t\t}\n\n\t\t\t// Check if it's a directory\n\t\t\tif fileInfo.IsDir() {\n\t\t\t\treturn fantasy.NewTextErrorResponse(fmt.Sprintf(\"Path is a directory, not a file: %s\", filePath)), nil\n\t\t\t}\n\n\t\t\t// Set default limit if not provided (no limit for SKILL.md files)\n\t\t\tif params.Limit <= 0 {\n\t\t\t\tif isSkillFile {\n\t\t\t\t\tparams.Limit = 1000000 // Effectively no limit for skill files\n\t\t\t\t} else {\n\t\t\t\t\tparams.Limit = DefaultReadLimit\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tisSupportedImage, mimeType := getImageMimeType(filePath)\n\t\t\tif isSupportedImage {","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/tools/view.go#L168-L204","documentation":"os.Stat(filePath) failed with an error other than NotExist (those become friendly \"File not found\" text responses with suggestions). The wrapped errno tells you what else went wrong — permission denied on a path component, too many symlinks, I/O error, etc.","triggerScenarios":"Reading a file whose parent directory (or the file) lacks read/search permission (EACCES), a symlink loop (ELOOP), a path component that is not a directory (ENOTDIR), or device I/O errors.","commonSituations":"Files under directories with restrictive permissions (root-owned, SSH keys, system dirs); broken mount points; macOS/SELinux sandbox denials; paths with a regular file where a directory is expected.","solutions":["Read the wrapped cause: EACCES → fix permissions (chmod/chown or run with access); ELOOP → fix the symlink; ENOTDIR → correct the path","Verify each path component with ls/stat as the same user the process runs as","Pick a readable copy of the file instead of the protected one","If outside the workdir, ensure the read permission request was granted — though denial normally yields a different response"],"exampleFix":"// before\n{\"file_path\":\"/root/.ssh/id_rsa\"} // stat: permission denied\n// after\nchmod o+r /path/to/readable/file  # or read a copy the user can access\n{\"file_path\":\"/home/user/project/file.txt\"}","handlingStrategy":"fallback","validationCode":"if _, err := os.Stat(path); err != nil && !os.IsNotExist(err) {\n    // EACCES/ELOOP/ENOTDIR etc. — resolve before calling the tool\n    return fmt.Errorf(\"path %q not accessible: %w\", path, err)\n}","typeGuard":"func isAccessibleFile(path string) bool {\n    st, err := os.Stat(path)\n    return err == nil && !st.IsDir()\n}","tryCatchPattern":"var pe *fs.PathError\nif errors.As(err, &pe) {\n    switch pe.Err {\n    case syscall.EACCES: // fix permissions / read an accessible copy\n    case syscall.ELOOP:  // fix symlink loop\n    case syscall.ENOTDIR: // correct the path\n    }\n}","preventionTips":["Pre-check readability with a stat/open probe as the same user","Avoid pointing the tool at root-owned or mode-0600 system files","Check for symlink loops before reading link-heavy paths","Grant the out-of-workdir read permission when prompted"],"tags":["filesystem","permissions","stat","errno"],"backgroundTag":"permission-denied","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}