aeron-io/aeron · error · AeronException
failed to write remove rcv destination command
Error message
failed to write remove rcv destination command
What it means
DriverProxy.removeRcvDestination claims space in the toDriverCommandBuffer to write a REMOVE_RCV_DESTINATION command. A negative tryClaim return means the ring buffer had no room for the message, so the command was never enqueued and AeronException is thrown. This indicates client-to-driver command backpressure or a non-consuming driver.
Solutions
- Confirm the media driver is alive and its agent thread is consuming commands
- Retry removeRcvDestination after a short backoff if the driver is only momentarily slow
- Throttle bulk destination removals (e.g., small sleep or batching between calls)
- For embedded drivers, ensure the driver agent thread is not blocked and enlarge the command queue if consistently saturated
- Treat repeated failures as driver death: close the client and reconnect/restart the driver
Example fix
// before
subscription.removeRcvDestination(channel);
// after
if (!driverProxy.isActive()) throw new IllegalStateException("driver stopped");
awaitCommandBufferDrained(); // ensure ring has capacity before claiming
subscription.removeRcvDestination(channel); Defensive patterns
Strategy: retry
Validate before calling
if (!aeron.context().isDriverActive()) {
throw new IllegalStateException("driver inactive; removeRcvDestination would fail");
} Try / catch
try {
subscription.removeRcvDestination(channel);
} catch (AeronException e) {
if (!e.getMessage().startsWith("failed to write")) throw e;
// retry with backoff; abort after N attempts
} Prevention
- Verify driver health before teardown bursts
- Stagger bulk destination removal during shutdown
- Keep control-command churn low on active subscriptions
- In tests, stop publications/subscriptions before stopping the driver
- Track claim-failure counts as a driver-stall signal
When it happens
Trigger: Calling Subscription.removeRcvDestination when the driver command ring is full — driver dead, paused (GC/debugger), or the client issued many commands in a tight loop faster than the driver drains.
Common situations: Driver terminated while client teardown code removes MDC destinations; bulk removal of many destinations in shutdown code; embedded driver agent thread blocked, leaving the command queue saturated.
Related errors
- failed to write add rcv destination command
- failed to write add counter command
- failed to write remove counter command
- failed to write reject image command
- failed to write next session id command
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/6d5b54df7c4dd43e.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-client/src/main/java/io/aeron/DriverProxy.java:345
return correlationId;
}
/**
* Remove a destination from the receive channel endpoint of an existing MDS Subscription.
*
* @param registrationId of the Subscription.
* @param endpointChannel used for the {@link #addRcvDestination(long, String)} command.
* @return the correlation id for the command.
*/
public long removeRcvDestination(final long registrationId, final String endpointChannel)
{
final long correlationId = toDriverCommandBuffer.nextCorrelationId();
final int length = DestinationMessageFlyweight.computeLength(endpointChannel.length());
final int index = toDriverCommandBuffer.tryClaim(REMOVE_RCV_DESTINATION, length);
if (index < 0)
{
throw new AeronException("failed to write remove rcv destination command");
}
destinationMessageFlyweight
.wrap(toDriverCommandBuffer.buffer(), index)
.registrationCorrelationId(registrationId)
.channel(endpointChannel)
.clientId(clientId)
.correlationId(correlationId);
toDriverCommandBuffer.commit(index);
return correlationId;
}
/**
* Add a new counter with a type id plus the label and key are provided in buffers.
*
* @param typeId for associating with the counter.View on GitHub (pinned to 6d60124e15)