{"record":{"id":"70ab3c725e0d05f1","repo":"yudai/gotty","slug":"unexpected-zero-length-read-from-master","errorCode":null,"errorMessage":"unexpected zero length read from master","messagePattern":"unexpected zero length read from master","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"webtty/webtty.go","lineNumber":160,"sourceCode":"\n\treturn nil\n}\n\nfunc (wt *WebTTY) masterWrite(data []byte) error {\n\twt.writeMutex.Lock()\n\tdefer wt.writeMutex.Unlock()\n\n\t_, err := wt.masterConn.Write(data)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to write to master\")\n\t}\n\n\treturn nil\n}\n\nfunc (wt *WebTTY) handleMasterReadEvent(data []byte) error {\n\tif len(data) == 0 {\n\t\treturn errors.New(\"unexpected zero length read from master\")\n\t}\n\n\tswitch data[0] {\n\tcase Input:\n\t\tif !wt.permitWrite {\n\t\t\treturn nil\n\t\t}\n\n\t\tif len(data) <= 1 {\n\t\t\treturn nil\n\t\t}\n\n\t\t_, err := wt.slave.Write(data[1:])\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"failed to write received data to slave\")\n\t\t}\n\n\tcase Ping:","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/yudai/gotty/blob/a080c85cbc59226c94c6941ad8c395232d72d517/webtty/webtty.go#L142-L178","documentation":"WebTTY's handleMasterReadEvent() guards against empty reads from the PTY master side. A zero-length slice carries no message type byte, so it cannot be dispatched; the library treats it as an unexpected condition rather than silently ignoring it.","triggerScenarios":"The master (PTY) read loop delivering a 0-byte data slice into handleMasterReadEvent — typically when a read returns success with no bytes or a caller passes an empty buffer.","commonSituations":"Race during PTY teardown where a read returns (nil/empty, nil); wrapping a slave whose Read returns 0, nil incorrectly (io.Reader implementations should return io.EOF instead of 0, nil).","solutions":["Check the wrapped PTY/slave reader: its Read must return io.EOF at end-of-stream, never (0, nil)","Skip zero-length reads in custom slave implementations before invoking WebTTY","If it happens at shutdown, treat it as benign teardown noise"],"exampleFix":"// before (custom slave Read)\nreturn 0, nil\n// after\nif n == 0 && err == nil {\n    return 0, io.EOF\n}\nreturn n, err","handlingStrategy":"type-guard","validationCode":"if len(data) > 0 {\n    if err := wt.handleMasterReadEvent(data); err != nil { ... }\n}","typeGuard":"func readableData(data []byte) bool { return len(data) > 0 }","tryCatchPattern":"if err := runWebTTY(ctx); err != nil {\n    if err.Error() == \"unexpected zero length read from master\" {\n        // treat as EOF/teardown or wrap slave reads to skip empties\n    }\n}","preventionTips":["Implement io.Reader for PTY slaves correctly: return io.EOF, never (0, nil)","Filter empty reads before dispatching into WebTTY"],"tags":["pty","webtty","io"],"backgroundTag":"zero-length-read","analyzedSha":"a080c85cbc59226c94c6941ad8c395232d72d517","analyzedAt":"2026-09-02T16:42:38.150Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}