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
- Treat this as normal stream termination when the client intentionally disconnects — catch and ignore on the server or abort the stream.
- Client side: keep the connection alive (disable idle timeouts, use keep-alive) for long builds.
- Retry the log download from scratch or from a known offset if the stream drops.
- 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
- Keep clients alive through quiet periods (timeouts > server wait interval of 5s).
- Disable aggressive proxy buffering/timeout for streaming routes.
- Treat RuntimeException(IOException) during streaming as expected termination.
- Avoid closing the connection abruptly mid-download from client code.
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
- Unable to discover cluster ip from database connection url:
- Loopback address not allowed for target docker image of push
- java.lang.InterruptedException
- Skipped only
- Error reading chart archive: ${e.getMessage()}
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/36e443affddf625e.
Report an issue: GitHub.