aeron-io/aeron · error · AeronException

failed to write remove subscription command

Error message

failed to write remove subscription command

What it means

DriverProxy.removeSubscription() throws AeronException when tryClaim(REMOVE_SUBSCRIPTION, length) cannot reserve space in the client-to-driver command buffer, so the removal command could not be written. Like removePublication, Aeron fails fast because a failed removal would leave driver-side state inconsistent with the client.

Solutions

  1. Close subscriptions before stopping the media driver in your shutdown sequence.
  2. Make driver-side handler callbacks non-blocking so command consumption never stalls.
  3. Wrap close() calls in try-catch during shutdown when the driver may already be gone.

Example fix

// before
subscription.close();
aeron.close();
driver.close();
// after
subscription.close();
aeron.close();
driver.close(); // driver closed last
// plus: try { subscription.close(); } catch (AeronException e) { /* driver already gone */ }
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try {
    subscription.close();
} catch (AeronException e) {
    log.warn("removeSubscription failed during shutdown", e);
}

Prevention

When it happens

Trigger: Calling Subscription.close() (or Aeron.removeSubscription) while the driver is dead/blocked and the command buffer is full; also during client conductor shutdown racing with subscription release.

Common situations: Application shutdown where the driver was stopped first; driver conductor stalled by a slow image-unavailable handler; runaway add/remove subscription churn overflowing the buffer.

Related errors


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/bfa5f22567f301cf. Report an issue: GitHub.

Appendix: source

Thrown at aeron-client/src/main/java/io/aeron/DriverProxy.java:201

        toDriverCommandBuffer.commit(index);

        return correlationId;
    }

    /**
     * Instruct the driver to remove a subscription by its registration id.
     *
     * @param registrationId for the subscription to be removed.
     * @return the correlation id for the command.
     */
    public long removeSubscription(final long registrationId)
    {
        final long correlationId = toDriverCommandBuffer.nextCorrelationId();
        final int index = toDriverCommandBuffer.tryClaim(REMOVE_SUBSCRIPTION, RemoveSubscriptionFlyweight.length());
        if (index < 0)
        {
            throw new AeronException("failed to write remove subscription command");
        }

        removeSubscriptionFlyweight
            .wrap(toDriverCommandBuffer.buffer(), index)
            .registrationId(registrationId)
            .clientId(clientId)
            .correlationId(correlationId);

        toDriverCommandBuffer.commit(index);

        return correlationId;
    }

    /**
     * Add a destination to the send channel of an existing MDC Publication.
     *
     * @param registrationId  of the Publication.
     * @param endpointChannel for the destination.

View on GitHub (pinned to 6d60124e15)