{"record":{"id":"c6c9e57af3d7d7e4","repo":"kovidgoyal/kitty","slug":"the-items-to-be-diffed-should-both-be-either-direc","errorCode":null,"errorMessage":"The items to be diffed should both be either directories or files. Comparing a directory to a file is not valid.'","messagePattern":"The items to be diffed should both be either directories or files\\. Comparing a directory to a file is not valid\\.'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kittens/diff/main.go","lineNumber":167,"sourceCode":"\t}\n\tright, err := get_remote_file(args[1])\n\tif err != nil {\n\t\treturn 1, err\n\t}\n\tdefer func() {\n\t\tfor _, path := range temp_files {\n\t\t\tos.Remove(path)\n\t\t}\n\t}()\n\tvar left_is_dir, right_is_dir bool\n\tif left, left_is_dir, err = resolve_path(left); err != nil {\n\t\treturn 1, err\n\t}\n\tif right, right_is_dir, err = resolve_path(right); err != nil {\n\t\treturn 1, err\n\t}\n\tif left_is_dir != right_is_dir {\n\t\treturn 1, fmt.Errorf(\"The items to be diffed should both be either directories or files. Comparing a directory to a file is not valid.'\")\n\t}\n\n\tlp, err = loop.New()\n\tloop.MouseTrackingMode(lp, loop.BUTTONS_AND_DRAG_MOUSE_TRACKING)\n\tif err != nil {\n\t\treturn 1, err\n\t}\n\tlp.ColorSchemeChangeNotifications()\n\th := Handler{left: left, right: right, lp: lp}\n\tlp.OnInitialize = func() (string, error) {\n\t\tlp.SetCursorVisible(false)\n\t\tlp.SetCursorShape(loop.BAR_CURSOR, true)\n\t\tlp.AllowLineWrapping(false)\n\t\tlp.SetWindowTitle(fmt.Sprintf(\"%s vs. %s\", left, right))\n\t\tlp.QueryCapabilities()\n\t\th.initialize()\n\t\treturn \"\", nil\n\t}","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kittens/diff/main.go#L149-L185","documentation":"The diff kitten resolves both positional paths and checks their filesystem types before starting the TUI. It refuses to compare a directory with a regular file because its diff driver (configurable via diff_cmd) operates on two like-typed inputs. The check uses the resolved (symlink-followed) type of each path.","triggerScenarios":"Calling `kitty +kitten diff file.txt somedir/` or `kitty +kitten diff dir/ file.txt`; a symlink on one side resolving to a different type than the other side appears to be; a path that is a socket/fifo/device being classified differently than the plain file on the other side.","commonSituations":"Scripts that compare `$file` against a backup directory; mistyping one side so it hits a directory; a symlinked config path pointing to a directory while the other side is a file; NFS or FUSE mounts reporting odd file types.","solutions":["Make both sides the same type: either two files or two directories.","If comparing a file to a directory, pick the specific file inside the directory to compare against.","If symlinks are involved, check what they resolve to (ls -l / readlink -f) and point at the real targets."],"exampleFix":"# before\nkitty +kitten diff ./config.toml ./backup/\n\n# after\nkitty +kitten diff ./config.toml ./backup/config.toml","handlingStrategy":"validation","validationCode":"// Go: ensure both sides are the same kind before launching\nst1, err1 := os.Stat(left)\nst2, err2 := os.Stat(right)\nif err1 != nil || err2 != nil {\n    log.Fatal(\"stat failed\", err1, err2)\n}\nif st1.IsDir() != st2.IsDir() {\n    log.Fatal(\"both paths must be files or both directories\")\n}","typeGuard":"func sameKind(a, b string) bool {\n    sa, ea := os.Stat(a)\n    sb, eb := os.Stat(b)\n    return ea == nil && eb == nil && sa.IsDir() == sb.IsDir()\n}","tryCatchPattern":"On error, inspect the message text; if it mentions 'directory to a file', resolve the intended file inside the directory and retry once with corrected paths.","preventionTips":["Stat both paths and compare IsDir() before invoking.","Resolve symlinks (filepath.EvalSymlinks) so types reflect real targets.","In scripts, guard against accidentally passing a directory where a file is expected."],"tags":["kitty","diff-kitten","filesystem","type-mismatch"],"backgroundTag":"file-type-mismatch","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}