apache/incubator-seata · error · RuntimeException

IO Exception during next()

Error message

IO Exception during next()

What it means

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.

Source

Thrown at common/src/main/java/org/apache/seata/common/util/SeataHttpWatch.java:177

            Read a single line and parse it as an event.
            Format: "{prefix}{json}\n" where prefix is defined in Constants.WATCH_EVENT_PREFIX.
            Each line is a complete event, event type is included in the JSON data.
            */
            String line = source.readUtf8Line();
            if (line == null) {
                throw new RuntimeException("Stream closed unexpectedly");
            }

            if (!line.startsWith(Constants.WATCH_EVENT_PREFIX)) {
                throw new RuntimeException("Invalid event format: expected prefix '" + Constants.WATCH_EVENT_PREFIX
                        + "', got: " + (line.length() > 20 ? line.substring(0, 20) + "..." : line));
            }

            String jsonData = line.substring(Constants.WATCH_EVENT_PREFIX.length());
            return parseEvent(jsonData);

        } catch (IOException e) {
            throw new RuntimeException("IO Exception during next()", e);
        }
    }

    /**
     * Parse event JSON into Response object.
     * Simplified format: only contains group, timestamp, and metadata fields.
     *
     * @param json the JSON string to parse
     * @return the parsed Response object
     * @throws IOException if parsing fails
     */
    private Response<T> parseEvent(String json) throws IOException {
        try {
            T eventData = JsonCodecFactory.getCodec().parseObject(json, eventType);
            return new Response<>(Response.Type.UPDATE, eventData);

        } catch (Exception e) {
            LOGGER.error("Failed to parse event JSON: {}", json, e);

View on GitHub (pinned to e01f97c6db)

Solutions

  1. Inspect the cause chain — SocketTimeoutException means readTimeout is too short for a quiet stream; 'connection reset' points to intermediary or peer drops.
  2. Raise okhttp readTimeout to 0 (no timeout) or a value larger than the longest expected gap between events.
  3. Enable TCP keepalive / server-side heartbeats so idle connections are not dropped.
  4. Wrap iteration in a reconnect loop with backoff as streams are inherently failure-prone.

Example fix

// before
OkHttpClient client = new OkHttpClient.Builder()
        .readTimeout(10, TimeUnit.SECONDS) // kills quiet SSE streams
        .build();

// after
OkHttpClient client = new OkHttpClient.Builder()
        .readTimeout(0, TimeUnit.MILLISECONDS) // stream never times out between events
        .retryOnConnectionFailure(true)
        .build();
Defensive patterns

Strategy: retry

Validate before calling

OkHttpClient client = new OkHttpClient.Builder()
        .readTimeout(0, TimeUnit.MILLISECONDS) // event streams must not time out between events
        .retryOnConnectionFailure(true)
        .build();

Try / catch

catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause instanceof java.net.SocketTimeoutException) {
        throw new IllegalStateException("readTimeout too short for watch stream", e);
    }
    scheduleReconnectWithBackoff(); // reset / broken pipe -> reconnect
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/incubator-seata@e01f97c6db (2026-08-14). Data as JSON: /api/errors/53c0186033b702e5. Report an issue: GitHub.