aeron-io/aeron · error · ControlProtocolException
GENERIC_ERROR
GENERIC_ERROR
Error message
Invalidation reason must be ${MAX_ERROR_MESSAGE_LENGTH} bytes or less What it means
Thrown by the driver conductor when processing an image rejection request (onRejectImage) whose reason string exceeds ErrorFlyweight.MAX_ERROR_MESSAGE_LENGTH (max bytes an error message can occupy in the control protocol flyweight). The rejection reason travels inside a fixed-size control message buffer, so an oversized reason cannot be encoded and the request is rejected with a ControlProtocolException of code GENERIC_ERROR. This is a caller-side input validation failure, not an internal driver fault.
Solutions
- Truncate the reason string to ErrorFlyweight.MAX_ERROR_MESSAGE_LENGTH bytes before calling rejectImage
- Log the full diagnostics separately and pass a short fixed reason such as "rejected by application policy"
- Check reason.length() client-side in a helper wrapper around rejectImage that clips to the limit
- Upgrade/downgrade client and driver together so both agree on the message length limit
Example fix
// before
subscription.rejectImage(image.correlationId(), image.position(), "Rejected: " + detailedDiagnostics);
// after
String reason = "Rejected: " + detailedDiagnostics;
if (reason.length() > ErrorFlyweight.MAX_ERROR_MESSAGE_LENGTH)
{
reason = reason.substring(0, ErrorFlyweight.MAX_ERROR_MESSAGE_LENGTH);
}
subscription.rejectImage(image.correlationId(), image.position(), reason); Defensive patterns
Strategy: validation
Validate before calling
if (reason == null || reason.length() > ErrorFlyweight.MAX_ERROR_MESSAGE_LENGTH)
{
reason = reason != null ? reason.substring(0, ErrorFlyweight.MAX_ERROR_MESSAGE_LENGTH) : "rejected";
}
subscription.rejectImage(imageCorrelationId, position, reason); Type guard
static boolean isValidReason(String reason)
{
return reason != null && reason.length() <= ErrorFlyweight.MAX_ERROR_MESSAGE_LENGTH;
} Try / catch
try
{
subscription.rejectImage(id, position, reason);
}
catch (ControlProtocolException ex)
{
log.warn("rejectImage rejected: " + ex.getMessage());
} Prevention
- Clip reason strings to ErrorFlyweight.MAX_ERROR_MESSAGE_LENGTH before every rejectImage call
- Keep rejection reasons short and static; put detail in application logs
- Wrap rejectImage in a helper that enforces the limit
When it happens
Trigger: Calling Aeron.rejectImage(correlationId, position, reason) (via Aeron client or Subscription#rejectImage) with a reason string longer than ErrorFlyweight.MAX_ERROR_MESSAGE_LENGTH bytes; the driver throws before looking up the image.
Common situations: Applications building rejection reasons dynamically by concatenating diagnostics, stack traces, or long URIs; embedding user-supplied text as the reason; missing truncation when adapting legacy logging messages to rejectImage API introduced in newer Aeron versions.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/2593c601d6aef3a4.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-driver/src/main/java/io/aeron/driver/DriverConductor.java:1100
}
void onTerminateDriver(final DirectBuffer tokenBuffer, final int tokenOffset, final int tokenLength)
{
if (ctx.terminationValidator().allowTermination(ctx.aeronDirectory(), tokenBuffer, tokenOffset, tokenLength))
{
ctx.terminationHook().run();
}
}
void onRejectImage(
final long correlationId,
final long imageCorrelationId,
final long position,
final String reason)
{
if (reason.length() > ErrorFlyweight.MAX_ERROR_MESSAGE_LENGTH)
{
throw new ControlProtocolException(GENERIC_ERROR, "Invalidation reason must be " +
ErrorFlyweight.MAX_ERROR_MESSAGE_LENGTH + " bytes or less");
}
final PublicationImage publicationImage = findPublicationImage(imageCorrelationId);
if (null == publicationImage)
{
final IpcPublication foundPublication = getIpcPublication(imageCorrelationId);
if (null == foundPublication)
{
throw new ControlProtocolException(
GENERIC_ERROR, "Unable to resolve image for correlationId=" + imageCorrelationId);
}
foundPublication.reject(position, reason, this, cachedNanoClock.nanoTime());
}
elseView on GitHub (pinned to 6d60124e15)