{"record":{"id":"2bdbfe71f22adb3e","repo":"kovidgoyal/kitty","slug":"invalid-file-descriptor-d","errorCode":null,"errorMessage":"invalid file descriptor: %d","messagePattern":"invalid file descriptor: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kittens/clipboard/main.go","lineNumber":42,"sourceCode":"\treturn run_set_loop(opts, args)\n}\n\nfunc clipboard_main(cmd *cli.Command, opts *Options, args []string) (rc int, err error) {\n\tif opts.Password != \"\" {\n\t\tif opts.HumanName == \"\" {\n\t\t\treturn 1, fmt.Errorf(\"must specify --human-name when using a password\")\n\t\t}\n\t\tptype, val, found := strings.Cut(opts.Password, \":\")\n\t\tif !found {\n\t\t\treturn 1, fmt.Errorf(\"invalid password: %#v no password type specified\", opts.Password)\n\t\t}\n\t\tswitch ptype {\n\t\tcase \"text\":\n\t\t\topts.Password = val\n\t\tcase \"fd\":\n\t\t\tif fd, err := strconv.Atoi(val); err == nil {\n\t\t\t\tif f := os.NewFile(uintptr(fd), \"password-fd\"); f == nil {\n\t\t\t\t\treturn 1, fmt.Errorf(\"invalid file descriptor: %d\", fd)\n\t\t\t\t} else {\n\t\t\t\t\tdata, err := io.ReadAll(f)\n\t\t\t\t\tf.Close()\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn 1, fmt.Errorf(\"failed to read from file descriptor: %d with error: %w\", fd, err)\n\t\t\t\t\t}\n\t\t\t\t\topts.Password = strings.TrimRightFunc(string(data), unicode.IsSpace)\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treturn 1, fmt.Errorf(\"not a valid file descriptor number: %#v\", val)\n\t\t\t}\n\t\tcase \"file\":\n\t\t\tif data, err := os.ReadFile(val); err == nil {\n\t\t\t\topts.Password = strings.TrimRightFunc(string(data), unicode.IsSpace)\n\t\t\t} else {\n\t\t\t\treturn 1, fmt.Errorf(\"failed to read from file: %#v with error: %w\", val, err)\n\t\t\t}","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kittens/clipboard/main.go#L24-L60","documentation":"When --password fd:N is used, Go's os.NewFile is called with the given integer. If the runtime cannot turn that number into a usable *os.File (it returns nil), the kitten reports 'invalid file descriptor: N'. In practice this branch is rarely hit because most integers yield a non-nil File; read failures surface as error 303 instead.","triggerScenarios":"Passing `--password fd:N` where N is a number that cannot be wrapped into a file handle by os.NewFile at all (nil return), typically a degenerate value on the current platform.","commonSituations":"Typos in the fd number; platforms/runtime versions where os.NewFile returns nil for out-of-range descriptors; passing an fd that was never opened by the parent process (which usually fails later at read time instead).","solutions":["Ensure the file descriptor is actually open in the kitten process — open it in the parent shell: `kitten ... --password fd:3 3< password.txt`","Prefer the file: form (`--password file:/path/to/pw`) which avoids fd bookkeeping entirely","Double-check the fd number matches the one you redirected"],"exampleFix":"# before\nkitten clipboard get --human-name me --password fd:7   # fd 7 not open\n# after\nkitten clipboard get --human-name me --password fd:3 3< ~/.clipboard-pw","handlingStrategy":"validation","validationCode":"# verify the fd is open and readable before exec'ing kitten\nif ! { : <&3; } 2>/dev/null; then echo \"fd 3 not readable\"; exit 2; fi\nkitten clipboard get --human-name me --password fd:3 ...","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Open the fd in the parent shell with 3< file","Prefer --password file: to avoid fd arithmetic","Test fd readability with `: <&N` before use"],"tags":["kitty","clipboard","file-descriptor","password"],"backgroundTag":"invalid-file-descriptor","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}