kovidgoyal/kitty · error
failed to read from file descriptor: %d with error: %w
Error message
failed to read from file descriptor: %d with error: %w
What it means
After successfully wrapping --password fd:N into a *os.File, the kitten reads it to EOF. If the read itself fails (I/O error, closed pipe, bad fd at read time), the error is wrapped with the offending descriptor number and the underlying cause.
Source
Thrown at kittens/clipboard/main.go:47
if opts.HumanName == "" {
return 1, fmt.Errorf("must specify --human-name when using a password")
}
ptype, val, found := strings.Cut(opts.Password, ":")
if !found {
return 1, fmt.Errorf("invalid password: %#v no password type specified", opts.Password)
}
switch ptype {
case "text":
opts.Password = val
case "fd":
if fd, err := strconv.Atoi(val); err == nil {
if f := os.NewFile(uintptr(fd), "password-fd"); f == nil {
return 1, fmt.Errorf("invalid file descriptor: %d", fd)
} else {
data, err := io.ReadAll(f)
f.Close()
if err != nil {
return 1, fmt.Errorf("failed to read from file descriptor: %d with error: %w", fd, err)
}
opts.Password = strings.TrimRightFunc(string(data), unicode.IsSpace)
}
} else {
return 1, fmt.Errorf("not a valid file descriptor number: %#v", val)
}
case "file":
if data, err := os.ReadFile(val); err == nil {
opts.Password = strings.TrimRightFunc(string(data), unicode.IsSpace)
} else {
return 1, fmt.Errorf("failed to read from file: %#v with error: %w", val, err)
}
}
}
if len(args) > 0 {
return 0, run_mime_loop(opts, args)
}View on GitHub (pinned to 6d5d0c4406)
Solutions
- Verify the fd is readable: `ls -l /proc/self/fd/N` in the same process context, or test with `cat <&N`
- Keep the writer alive until the kitten has read the password, or use a regular file: `--password file:pw.txt`
- Check the underlying error message (%w) to identify the true errno (EBADF, EPIPE, etc.)
Example fix
# before kitten clipboard get --human-name me --password fd:3 # fd 3 is write-only # after kitten clipboard get --human-name me --password file:/etc/myapp/clipboard-pw
Defensive patterns
Strategy: fallback
Validate before calling
# fall back to file: if reading the fd may fail [ -r "$PWFILE" ] && PWARG="file:$PWFILE" || PWARG="fd:3"
Prevention
- Keep the writer process alive until the read completes
- Open fds read-only for password delivery
- Prefer regular files over pipes for password delivery
When it happens
Trigger: `--password fd:N` where the descriptor exists but reading fails: the write end of a pipe was closed, the fd refers to a write-only or closed handle, or the underlying file hit an I/O error during io.ReadAll.
Common situations: Opening a fd write-only and passing it for reading; the producer process exiting before the kitten reads; passing a socket or device fd that errors on read; fd inheritance issues under systemd or container runtimes that close inherited fds.
Related errors
- invalid file descriptor: %d
- not a valid file descriptor number: %#v
- Too much piped data
- Failed to read from STDIN pipe with error: %w
- Failed to create a temporary from STDIN pipe with error: %w
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/64bcaaab6397f521.
Report an issue: GitHub.