{"record":{"id":"53c0186033b702e5","repo":"apache/incubator-seata","slug":"io-exception-during-next","errorCode":null,"errorMessage":"IO Exception during next()","messagePattern":"IO Exception during next\\(\\)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"common/src/main/java/org/apache/seata/common/util/SeataHttpWatch.java","lineNumber":177,"sourceCode":"            Read a single line and parse it as an event.\n            Format: \"{prefix}{json}\\n\" where prefix is defined in Constants.WATCH_EVENT_PREFIX.\n            Each line is a complete event, event type is included in the JSON data.\n            */\n            String line = source.readUtf8Line();\n            if (line == null) {\n                throw new RuntimeException(\"Stream closed unexpectedly\");\n            }\n\n            if (!line.startsWith(Constants.WATCH_EVENT_PREFIX)) {\n                throw new RuntimeException(\"Invalid event format: expected prefix '\" + Constants.WATCH_EVENT_PREFIX\n                        + \"', got: \" + (line.length() > 20 ? line.substring(0, 20) + \"...\" : line));\n            }\n\n            String jsonData = line.substring(Constants.WATCH_EVENT_PREFIX.length());\n            return parseEvent(jsonData);\n\n        } catch (IOException e) {\n            throw new RuntimeException(\"IO Exception during next()\", e);\n        }\n    }\n\n    /**\n     * Parse event JSON into Response object.\n     * Simplified format: only contains group, timestamp, and metadata fields.\n     *\n     * @param json the JSON string to parse\n     * @return the parsed Response object\n     * @throws IOException if parsing fails\n     */\n    private Response<T> parseEvent(String json) throws IOException {\n        try {\n            T eventData = JsonCodecFactory.getCodec().parseObject(json, eventType);\n            return new Response<>(Response.Type.UPDATE, eventData);\n\n        } catch (Exception e) {\n            LOGGER.error(\"Failed to parse event JSON: {}\", json, e);","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/apache/incubator-seata/blob/e01f97c6db397165050caa6764020410c2c8199a/common/src/main/java/org/apache/seata/common/util/SeataHttpWatch.java#L159-L195","documentation":"Thrown from SeataHttpWatch.next() when reading a line from the event stream raises an IOException — the connection failed at the transport level (reset, timeout, broken pipe) rather than ending cleanly. The original IOException is attached as the cause for diagnosis.","triggerScenarios":"watch.next() with the socket dying mid-read: connection reset by peer, socket read timeout on the OkHttp client, TLS session torn down, or network path loss during event streaming.","commonSituations":"OkHttp client configured with a short readTimeout that fires on quiet streams; NAT/firewall dropping long-lived idle connections; server or intermediary resetting connections; mobile/unstable networks.","solutions":["Inspect the cause chain — SocketTimeoutException means readTimeout is too short for a quiet stream; 'connection reset' points to intermediary or peer drops.","Raise okhttp readTimeout to 0 (no timeout) or a value larger than the longest expected gap between events.","Enable TCP keepalive / server-side heartbeats so idle connections are not dropped.","Wrap iteration in a reconnect loop with backoff as streams are inherently failure-prone."],"exampleFix":"// before\nOkHttpClient client = new OkHttpClient.Builder()\n        .readTimeout(10, TimeUnit.SECONDS) // kills quiet SSE streams\n        .build();\n\n// after\nOkHttpClient client = new OkHttpClient.Builder()\n        .readTimeout(0, TimeUnit.MILLISECONDS) // stream never times out between events\n        .retryOnConnectionFailure(true)\n        .build();","handlingStrategy":"retry","validationCode":"OkHttpClient client = new OkHttpClient.Builder()\n        .readTimeout(0, TimeUnit.MILLISECONDS) // event streams must not time out between events\n        .retryOnConnectionFailure(true)\n        .build();","typeGuard":null,"tryCatchPattern":"catch (RuntimeException e) {\n    Throwable cause = e.getCause();\n    if (cause instanceof java.net.SocketTimeoutException) {\n        throw new IllegalStateException(\"readTimeout too short for watch stream\", e);\n    }\n    scheduleReconnectWithBackoff(); // reset / broken pipe -> reconnect\n}","preventionTips":["Set OkHttp readTimeout to 0 for SSE-style streams.","Enable TCP keepalive and server heartbeats so idle connections survive.","Always inspect the cause chain — it distinguishes config problems from network drops."],"tags":["network","io","timeout","watch","okhttp"],"backgroundTag":null,"analyzedSha":"e01f97c6db397165050caa6764020410c2c8199a","analyzedAt":"2026-08-14T10:23:53.097Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}