{"record":{"id":"3d41bc992447c7e4","repo":"kovidgoyal/kitty","slug":"failed-to-open-s-for-reading-with-error-w","errorCode":null,"errorMessage":"Failed to open %s for reading with error: %w","messagePattern":"Failed to open (.+?) for reading with error: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/cmd/edit_in_kitty/main.go","lineNumber":182,"sourceCode":"\t\treturn 1, tui.Canceled\n\t}\n\n\tds := lp.DeathSignalName()\n\tif ds != \"\" {\n\t\tfmt.Print(abort_msg)\n\t\tif kill_if_signaled {\n\t\t\tlp.KillIfSignalled()\n\t\t\treturn\n\t\t}\n\t\treturn 1, &tui.KilledBySignal{Msg: fmt.Sprint(\"Killed by signal: \", ds), SignalName: ds}\n\t}\n\treturn\n}\n\nfunc edit_in_kitty(path string, opts *Options) (exit_code int, err error) {\n\tread_file, err := os.Open(path)\n\tif err != nil {\n\t\treturn 1, fmt.Errorf(\"Failed to open %s for reading with error: %w\", path, err)\n\t}\n\tdefer read_file.Close()\n\tvar s unix.Stat_t\n\terr = unix.Fstat(int(read_file.Fd()), &s)\n\tif err != nil {\n\t\treturn 1, fmt.Errorf(\"Failed to stat %s with error: %w\", path, err)\n\t}\n\tif s.Size > int64(opts.MaxFileSize)*1024*1024 {\n\t\treturn 1, fmt.Errorf(\"File size %s is too large for performant editing\", humanize.Bytes(uint64(s.Size)))\n\t}\n\n\tfile_data, err := io.ReadAll(read_file)\n\tif err != nil {\n\t\treturn 1, fmt.Errorf(\"Failed to read from %s with error: %w\", path, err)\n\t}\n\tread_file.Close()\n\tdata := strings.Builder{}\n\tdata.Grow(len(file_data) * 4)","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/tools/cmd/edit_in_kitty/main.go#L164-L200","documentation":"edit_in_kitty could not os.Open the target file path for reading. The underlying OS error is wrapped; typical causes are the file not existing or the process lacking read permission on it. The function aborts with exit code 1 before doing anything else.","triggerScenarios":"Calling edit_in_kitty with a path that doesn't exist, is a dangling symlink, is a directory, or resides where the user has no read permission (or with a stale NFS handle).","commonSituations":"Editing a file that was just deleted/moved by another process, race between picking a file in a file manager and opening it, wrong CWD-relative path, or running as a user without access to root-owned files.","solutions":["Confirm the path exists and is a regular file: ls -l <path>","Use an absolute path to rule out CWD-relative resolution issues","Fix permissions (or run with appropriate privileges) if the file exists but is unreadable","If the file is being moved/deleted concurrently, re-resolve the path right before invoking the editor"],"exampleFix":"# before\nedit-in-kitty ./notes/../notes/old.txt   # ENOENT\n# after\nedit-in-kitty \"$(realpath old.txt)\"","handlingStrategy":"validation","validationCode":"// Resolve and check the file before calling the editor\nabs, err := filepath.Abs(path)\nif err != nil { return err }\nif info, err := os.Stat(abs); err != nil || info.IsDir() {\n    return fmt.Errorf(\"not an editable regular file: %s\", abs)\n}","typeGuard":"func isEditableFile(path string) bool {\n    info, err := os.Stat(path)\n    return err == nil && info.Mode().IsRegular()\n}","tryCatchPattern":"code, err := editInKitty(path, opts)\nif err != nil && errors.Is(err, fs.ErrNotExist) {\n    // file vanished: re-prompt user or re-resolve path\n}","preventionTips":["Pass absolute, symlink-resolved paths","Re-stat the file immediately before launching the editor","Handle ENOENT/EACCES distinctly so users get actionable messages"],"tags":["filesystem","file-not-found","permissions","go"],"backgroundTag":"file-open-failed","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}