theonedev/onedev · warning · RuntimeException

java.io.IOException

Error message

java.io.IOException

What it means

writeInt writes a 4-byte integer length prefix to the log stream's OutputStream. If the underlying connection is broken (client gone, socket closed) os.write throws IOException, which is wrapped in a RuntimeException. This is the streaming framework's way of aborting when the consumer disconnects.

Source

Thrown at server-core/src/main/java/io/onedev/server/rest/resource/BuildLogStreamResource.java:129

							} else {
								writeInt(os, 0);
								os.flush();
							}
						}
					}
				}
			} finally {
				sessionService.openSession();
				logService.deregisterListener(logListener);
			}
		};
	}
	
	private void writeInt(OutputStream os, int value) {
		try {
			os.write(ByteBuffer.allocate(Integer.BYTES).putInt(value).array());
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	private void writeStatus(OutputStream os, Status status) {
		try {
			writeInt(os, status.name().length() * -1);
			os.write(status.name().getBytes(UTF_8));
			os.flush();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	private void writeEntry(OutputStream os, JobLogEntryEx entry) {
		try {
			var bytes = objectMapper.writeValueAsBytes(entry.transformEmojis());
			writeInt(os, bytes.length);
			os.write(bytes);

View on GitHub (pinned to d44925c47c)

Solutions

  1. Treat this as normal stream termination when the client intentionally disconnects — catch and ignore on the server or abort the stream.
  2. Client side: keep the connection alive (disable idle timeouts, use keep-alive) for long builds.
  3. Retry the log download from scratch or from a known offset if the stream drops.
  4. Check intermediary proxies/firewalls for connection idle limits and raise them.

Example fix

// server-side view: RuntimeException wrapping means broken pipe
try {
    streamLog(os);
} catch (RuntimeException e) {
    if (e.getCause() instanceof IOException) {
        log.info("client disconnected while streaming build log");
        return; // normal termination
    }
    throw e;
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    consumeLogStream(in);
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause instanceof IOException) {
      log.warn("Log stream broken (client disconnect or network issue): " + cause.getMessage());
    } else throw e;
}

Prevention

When it happens

Trigger: Client disconnects while downloadLog is streaming; socket reset by load balancer; connection pool closed; any failure writing the binary length prefix for a status or log entry.

Common situations: User cancels the download mid-stream; proxy idle cutoff during slow builds; mobile/VPN clients dropping; browser tab closed while tailing a log.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/36e443affddf625e. Report an issue: GitHub.