{"record":{"id":"c4ff5bafed6f23a6","repo":"kovidgoyal/kitty","slug":"failed-to-read-from-stdin-pipe-with-error-w","errorCode":null,"errorMessage":"Failed to read from STDIN pipe with error: %w","messagePattern":"Failed to read from STDIN pipe with error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kittens/clipboard/legacy.go","lineNumber":77,"sourceCode":"\t\t\tif err == io.EOF {\n\t\t\t\terr = nil\n\t\t\t}\n\t\t\treturn b, err\n\t\t}\n\t}\n}\n\nfunc preread_stdin() (data_src io.Reader, tempfile *os.File, err error) {\n\t// we pre-read STDIN because otherwise if the output of a command is being piped in\n\t// and that command itself transmits on the tty we will break. For example\n\t// kitten @ ls | kitten clipboard\n\tvar stdin_data []byte\n\tstdin_data, err = read_all_with_max_size(os.Stdin, 2*1024*1024)\n\tif err == nil {\n\t\tos.Stdin.Close()\n\t} else if err != ErrTooMuchPipedData {\n\t\tos.Stdin.Close()\n\t\terr = fmt.Errorf(\"Failed to read from STDIN pipe with error: %w\", err)\n\t\treturn\n\t}\n\tif err == ErrTooMuchPipedData {\n\t\ttempfile, err = utils.CreateAnonymousTemp(\"\")\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"Failed to create a temporary from STDIN pipe with error: %w\", err)\n\t\t}\n\t\ttempfile.Write(stdin_data)\n\t\t_, err = io.Copy(tempfile, os.Stdin)\n\t\tos.Stdin.Close()\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"Failed to copy data from STDIN pipe to temp file with error: %w\", err)\n\t\t}\n\t\ttempfile.Seek(0, io.SeekStart)\n\t\tdata_src = tempfile\n\t} else if stdin_data != nil {\n\t\tdata_src = bytes.NewBuffer(stdin_data)\n\t}","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kittens/clipboard/legacy.go#L59-L95","documentation":"The clipboard kitten prereads STDIN (up to 2MB) before interacting with the terminal. If reading os.Stdin fails with something other than the too-much-data sentinel, this wrapped error is returned. It usually means the pipe was broken or closed prematurely.","triggerScenarios":"Piping from a process that exits/closes the pipe early, e.g. 'echo foo | kitty +kitten clipboard' where the writer fails, or STDIN redirected to a closed fd.","commonSituations":"Broken pipe from an upstream command crash, piping from a process killed by a signal, or running with STDIN closed (</dev/null is fine since read succeeds).","solutions":["Check the upstream command in the pipeline actually succeeds","Retry the pipeline ensuring the writer keeps STDIN open until done","Inspect the wrapped %w error for the real OS cause (EPIPE, EBADF)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// ensure the producer keeps stdin open, e.g. with a fifo held open","typeGuard":null,"tryCatchPattern":"data, tf, err := preread_stdin()\nif err != nil { return fmt.Errorf(\"reading stdin: %w\", err) } // inspect wrapped errors.Error() for EPIPE","preventionTips":["Verify upstream pipeline commands succeed before piping into the kitten","Don't close STDIN early in custom producers"],"tags":["kitty","clipboard","stdin","pipe-error"],"backgroundTag":"stdin-read-failed","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}