aeron-io/aeron · error · AeronException
failed to write reject image command
Error message
failed to write reject image command
What it means
DriverProxy.rejectImage claims space in the toDriverCommandBuffer to write a REJECT_IMAGE command carrying a reason string. tryClaim returned negative because the ring buffer had no capacity for RejectImageFlyweight.computeLength(reason), so AeronException is thrown and the rejection was never delivered to the driver. Note in this method the correlationId is fetched after the claim, so a failed claim leaves no partial message.
Solutions
- Check the media driver is alive and draining the command queue before rejecting images
- Retry rejectImage with backoff; capacity returns once the driver catches up
- Reduce concurrent control-command bursts around rejection logic
- Shorten the reject reason string — smaller messages fit more easily in a nearly-full ring
- If the driver is unresponsive, treat the connection as lost and re-establish client and subscription instead of retrying indefinitely
Example fix
// before
image.reject("unauthorized stream");
// after
try {
image.reject("unauthorized stream");
} catch (AeronException e) {
if (!driverProxy.isActive()) throw e;
Thread.sleep(10);
image.reject("unauthorized stream"); // retry once driver drains queue
} Defensive patterns
Strategy: retry
Validate before calling
if (!aeron.context().isDriverActive()) {
throw new IllegalStateException("driver inactive; image rejection cannot be delivered");
} Try / catch
try {
image.reject(reason);
} catch (AeronException e) {
if (!e.getMessage().startsWith("failed to write")) throw e;
// short backoff then retry; if driver is dead, close the subscription instead
} Prevention
- Check driver liveness before rejecting images
- Keep reject reason strings short
- Avoid rejecting images during heavy control-command churn
- On repeated failure, drop the subscription rather than retrying forever
- Monitor driver queue drain rate in high-churn systems
When it happens
Trigger: Calling Image.reject(reason) (via DriverProxy.rejectImage) when the client-driver command ring is full: driver dead or stalled, or a burst of control commands (connect/disconnect, destination changes) saturated the queue.
Common situations: A subscriber refusing an image during high-churn periods when many control commands are in flight; media driver crashed; driver agent blocked by slow recording (Archive) or a hung MDC destination.
Related errors
- failed to write add rcv destination command
- failed to write remove rcv destination command
- failed to write add counter command
- failed to write remove counter command
- failed to write next session id command
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/e66bc3f9a21e5719.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-client/src/main/java/io/aeron/DriverProxy.java:520
/**
* Reject a specific image.
*
* @param imageCorrelationId of the image to be invalidated
* @param position of the image when invalidation occurred
* @param reason user supplied reason for invalidation, reported back to publication
* @return the correlationId of the request for invalidation.
*/
public long rejectImage(
final long imageCorrelationId,
final long position,
final String reason)
{
final int length = RejectImageFlyweight.computeLength(reason);
final int index = toDriverCommandBuffer.tryClaim(REJECT_IMAGE, length);
if (index < 0)
{
throw new AeronException("failed to write reject image command");
}
final long correlationId = toDriverCommandBuffer.nextCorrelationId();
rejectImageFlyweight
.wrap(toDriverCommandBuffer.buffer(), index)
.clientId(clientId)
.correlationId(correlationId)
.imageCorrelationId(imageCorrelationId)
.position(position)
.reason(reason);
toDriverCommandBuffer.commit(index);
return correlationId;
}
View on GitHub (pinned to 6d60124e15)