aeron-io/aeron · error · ArchiveEvent
response publication is at max position: " + session
Error message
response publication is at max position: " + session
What it means
ControlResponseProxy.checkResult throws ArchiveEvent (Category.ERROR) when the control response publication offer returns Publication.MAX_POSITION_EXCEEDED, meaning the response stream reached the term buffer's maximum position and cannot wrap — the publication cannot progress further. The session is aborted with 'control response publication is at max position'.
Solutions
- Increase the control response channel term length (term-length URL param on the archive control response channel) so max position is not reachable in practice
- Replace long-lived control sessions: clients should disconnect and create a fresh session periodically instead of reusing one indefinitely
- Avoid streaming large result sets through the control response channel in unbounded loops; page or batch them
- Catch ArchiveEvent and abort/close the session so the client can reconnect with a new session
Example fix
// before: default tiny term buffers on control response channel
Aeron.Context ctx = new Aeron.Context();
// archive control-mode response channel without term-length
// after: configure adequate term length
String responseChannel = "aeron:udp?endpoint=localhost:8020|term-length=1m";
Archive.Context archiveCtx = new Archive.Context()
.controlResponseChannel(responseChannel); Defensive patterns
Strategy: try-catch
Validate before calling
long maxPosition = 1L << 62; // generous default; if (publication.position() > maxPosition) recreate session
Try / catch
try { proxy.sendResponse(...); }
catch (ArchiveEvent e)
{
if (e.getMessage().startsWith("response publication is at max position")) { session.abort(e.getMessage()); session.close(); }
else { throw e; }
} Prevention
- Configure a large term-length on the control response channel (e.g. 1m or more)
- Recycle long-lived control sessions periodically instead of reusing one forever
- Avoid unbounded descriptor/response streaming on a single session
- Alert on publication position growth on control response streams
When it happens
Trigger: sendDescriptor, sendResponse, or send pushing so much data on the control response stream that its position exceeds the publication's max position (term length * 2^31) — effectively an exhausted publication from huge descriptor/response volumes or misconfigured (too small) term buffers on a very long-lived session.
Common situations: Very long-lived control sessions sending enormous numbers of responses; sending large recording descriptors in a loop; term-length misconfigured far too small for the response traffic volume.
Related errors
- ControlSession.RESPONSE_NOT_CONNECTED_MSG + ": " + session
- response publication is closed: " + session
- failed to offer async replay response
- name + " cannot be negative: value=" + value
- recording events publication at max position, term-length="…
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/3dbca8b0c66bc176.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-archive/src/main/java/io/aeron/archive/ControlResponseProxy.java:259
private static void checkResult(final ControlSession session, final long result)
{
if (result == Publication.NOT_CONNECTED)
{
session.abort(ControlSession.RESPONSE_NOT_CONNECTED_MSG);
throw new ArchiveEvent(ControlSession.RESPONSE_NOT_CONNECTED_MSG + ": " + session);
}
if (result == Publication.CLOSED)
{
session.abort("control response publication is closed");
throw new ArchiveEvent("response publication is closed: " + session, AeronException.Category.ERROR);
}
if (result == Publication.MAX_POSITION_EXCEEDED)
{
session.abort("control response publication is at max position");
throw new ArchiveEvent(
"response publication is at max position: " + session, AeronException.Category.ERROR);
}
}
private void logSendResponse(final DirectBuffer buffer, final int offset, final int length)
{
ArchiveTracing.traceControlResponse(buffer, offset, length);
}
private void logSendSignal(final DirectBuffer buffer, final int offset, final int length)
{
ArchiveTracing.traceRecordingSignal(buffer, offset, length);
}
}
View on GitHub (pinned to 6d60124e15)