{"record":{"id":"bd017c5c28984c02","repo":"kovidgoyal/kitty","slug":"s-is-not-readable-and-writeable","errorCode":null,"errorMessage":"%s is not readable and writeable","messagePattern":"(.+?) is not readable and writeable","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/cmd/edit_in_kitty/main.go","lineNumber":213,"sourceCode":"\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)\n\n\tadd := func(key, val string) {\n\t\tif data.Len() > 0 {\n\t\t\tdata.WriteString(\",\")\n\t\t}\n\t\tdata.WriteString(key)\n\t\tdata.WriteString(\"=\")\n\t\tdata.WriteString(val)\n\t}\n\tadd_encoded := func(key, val string) { add(key, encode(val)) }\n\n\tif unix.Access(path, unix.R_OK|unix.W_OK) != nil {\n\t\treturn 1, fmt.Errorf(\"%s is not readable and writeable\", path)\n\t}\n\tcwd, err := os.Getwd()\n\tif err != nil {\n\t\treturn 1, fmt.Errorf(\"Failed to get the current working directory with error: %w\", err)\n\t}\n\tadd_encoded(\"cwd\", cwd)\n\tfor _, arg := range os.Args[2:] {\n\t\tadd_encoded(\"a\", arg)\n\t}\n\tadd(\"file_inode\", fmt.Sprintf(\"%d:%d:%d\", s.Dev, s.Ino, s.Mtim.Nano()))\n\tadd_encoded(\"file_data\", utils.UnsafeBytesToString(file_data))\n\tfmt.Println(\"Waiting for editing to be completed, press Esc to abort...\")\n\twrite_data := func(data_type string, rdata []byte) (err error) {\n\t\terr = utils.AtomicWriteFile(path, bytes.NewReader(rdata), fs.FileMode(s.Mode).Perm())\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"Failed to write data to %s with error: %w\", path, err)\n\t\t}\n\t\treturn","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/tools/cmd/edit_in_kitty/main.go#L195-L231","documentation":"Before handing the file to kitty, edit_in_kitty checks unix.Access(path, R_OK|W_OK) and aborts if the process can't both read and write it. This is a preflight check distinct from the earlier open: it explicitly requires write access too, since the editor will save the file back.","triggerScenarios":"Calling edit_in_kitty on a file the effective user can read but not write (root-owned file, no group/other write bit, read-only mount), or vice versa. Any non-nil Access result aborts.","commonSituations":"Editing system config files as a non-root user, files on read-only mounts (RO remount, immutable flag), or files owned by another user without write permission.","solutions":["Fix permissions: chmod/chown as appropriate, or run under a user with write access","Check for a read-only mount (mount -o remount,rw) or immutable attribute (lsattr; chattr -i)","If the file shouldn't be modified, use a read-only pager instead of this editor","Sudo only the edit step: sudo -e or run edit_in_kitty via sudo if policy allows"],"exampleFix":"# before\nedit-in-kitty /etc/app/config.yaml   # EACCES: not writable\n# after\nsudo edit-in-kitty /etc/app/config.yaml\n# or: chmod u+w /etc/app/config.yaml (if you own it)","handlingStrategy":"validation","validationCode":"// Pre-check read+write access exactly like the tool does\nif err := unix.Access(path, unix.R_OK|unix.W_OK); err != nil {\n    return fmt.Errorf(\"need read+write on %s — fix perms or use sudo\", path)\n}","typeGuard":"func isReadableWritable(path string) bool {\n    return unix.Access(path, unix.R_OK|unix.W_OK) == nil\n}","tryCatchPattern":"code, err := editInKitty(path, opts)\nif err != nil && strings.Contains(err.Error(), \"not readable and writeable\") {\n    // escalate deliberately rather than blanket-sudo\n    exec.Command(\"sudo\", os.Args[0], path).Run()\n}","preventionTips":["Check lsattr for immutable files before editing system configs","Detect read-only mounts up front and suggest a copy-edit-write-back flow"],"tags":["filesystem","permissions","access-denied","go"],"backgroundTag":"file-permission-denied","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}