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

  1. Check the media driver is alive and draining the command queue before rejecting images
  2. Retry rejectImage with backoff; capacity returns once the driver catches up
  3. Reduce concurrent control-command bursts around rejection logic
  4. Shorten the reject reason string — smaller messages fit more easily in a nearly-full ring
  5. 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

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


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)