{"record":{"id":"21b20ea9db93cce9","repo":"wavetermdev/waveterm","slug":"error-reading-input-w","errorCode":null,"errorMessage":"error reading input: %w","messagePattern":"error reading input: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshcmdreader.go","lineNumber":83,"sourceCode":"\tb.CVar.Broadcast()\n}\n\nfunc (b *PtyBuffer) processWaveEscSeq(escSeq []byte) {\n\tb.MessageCh <- baseds.RpcInputChType{MsgBytes: escSeq}\n}\n\nfunc (b *PtyBuffer) run() {\n\tdefer close(b.MessageCh)\n\tbuf := make([]byte, 4096)\n\tfor {\n\t\tn, err := b.InputReader.Read(buf)\n\t\tb.processData(buf[:n])\n\t\tif err == io.EOF {\n\t\t\tb.setEOF()\n\t\t\treturn\n\t\t}\n\t\tif err != nil {\n\t\t\tb.setErr(fmt.Errorf(\"error reading input: %w\", err))\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc (b *PtyBuffer) processData(data []byte) {\n\toutputBuf := make([]byte, 0, len(data))\n\tfor _, ch := range data {\n\t\tif b.EscMode == Mode_WaveEsc {\n\t\t\tif ch == ESC {\n\t\t\t\t// terminates the escape sequence (and the rest was invalid)\n\t\t\t\tb.EscMode = Mode_Normal\n\t\t\t\toutputBuf = append(outputBuf, b.EscSeqBuf...)\n\t\t\t\toutputBuf = append(outputBuf, ch)\n\t\t\t\tb.EscSeqBuf = nil\n\t\t\t} else if ch == BEL || ch == ST {\n\t\t\t\t// terminates the escpae sequence (is a valid Wave OSC command)\n\t\t\t\tb.EscMode = Mode_Normal","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshcmdreader.go#L65-L101","documentation":"PtyBuffer.run reads from the underlying PTY/pipe reader in a loop and hands bytes to processData. If a read returns an error other than io.EOF, the buffer stores it wrapped as \"error reading input: %w\" and stops. Anyone reading from the PtyBuffer (MakePtyBuffer consumers) subsequently receives this error, meaning the terminal data stream terminated abnormally rather than cleanly at EOF.","triggerScenarios":"The PTY master/child side is closed abruptly (process killed, file descriptor invalid), an I/O error occurs on the underlying reader (EIO after the child exits on Linux PTYs), or the source file/pipe is closed while MakePtyBuffer is still reading.","commonSituations":"Shell process crashes or is OOM-killed while output is being streamed; terminal block reading a PTY whose child exited causing EIO instead of EOF; container/SSH sessions dropping mid-stream.","solutions":["Inspect the wrapped inner error (%w) — on Linux an EIO from a PTY read after the child exits usually means the process ended; treat it as end-of-stream if exit status is already captured.","Check the state of the process attached to the PTY (wsh ps / ps aux) and restart it if it died unexpectedly.","Ensure the reader backing the PtyBuffer is valid and not closed by another goroutine; close the buffer itself when done to avoid reading a dead fd.","If this happens reproducibly on session exit, upgrade Wave Terminal — PTY teardown handling (EIO-as-EOF) is a common PTY library fix."],"exampleFix":"// before: reading from a PtyBuffer whose PTY died, surfacing raw error\ndata, err := ptyBuffer.Read(ctx) // error reading input: read /dev/ptmx: input/output error\n// after: tolerate EIO-at-exit as normal termination\ndata, err := ptyBuffer.Read(ctx)\nif err != nil && strings.Contains(err.Error(), \"input/output error\") && cmdDone {\n    err = io.EOF // process already exited; treat as end of stream\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"data, err := ptyBuffer.Read(ctx)\nif err != nil {\n    var ptyErr error\n    if errors.As(err, &ptyErr) && strings.Contains(err.Error(), \"error reading input\") {\n        if isEioAfterExit(err) { // treat EIO after child exit as EOF\n            return io.EOF\n        }\n        return fmt.Errorf(\"pty stream failed: %w\", err)\n    }\n    return err\n}","preventionTips":["Always close the PtyBuffer when the underlying process exits to stop reads on a dead fd.","Treat PTY EIO after child exit as end-of-stream, not a fatal error.","Monitor the attached process health; restart the shell if it was killed.","Keep Wave Terminal updated — PTY teardown behavior differs across platforms and is patched regularly."],"tags":["pty","io","terminal","waveterm"],"backgroundTag":"pty-read-error","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}