aeron-io/aeron · error · AeronException
failed to write add counter command
Error message
failed to write add counter command
What it means
DriverProxy.addCounter claims space in the toDriverCommandBuffer to write an ADD_COUNTER command carrying key and label buffers. tryClaim returned negative because the ring lacked capacity for CounterMessageFlyweight.computeLength(keyLength, labelLength) bytes, so AeronException is thrown. The counter was not created; the client could not hand the command to the driver.
Solutions
- Check the media driver is running and consuming commands before allocating counters
- Retry addCounter with backoff — the claim failure is transient if the driver is draining
- Reduce the burst rate of counter creation; create counters lazily or in stages
- Keep counter key/label sizes small to reduce required claim size
- For embedded drivers, verify the driver agent thread health and increase command buffer capacity if saturation is recurring
Example fix
// before
Counter c = aeron.addCounter( typeId, keyBuffer, 0, keyLength, labelBuffer, 0, labelLength);
// after
Counter c;
int attempts = 0;
do {
try {
c = aeron.addCounter(typeId, keyBuffer, 0, keyLength, labelBuffer, 0, labelLength);
break;
} catch (AeronException e) {
if (++attempts > 5 || !driverProxy.isActive()) throw e;
Thread.sleep(10 * attempts);
}
} while (true); Defensive patterns
Strategy: retry
Validate before calling
if (!aeron.context().isDriverActive()) {
throw new IllegalStateException("driver inactive; addCounter would fail");
}
if (keyLength < 0 || labelLength < 0) {
throw new IllegalArgumentException("negative counter key/label length");
} Try / catch
try {
Counter c = aeron.addCounter(typeId, keyBuffer, keyOffset, keyLength, labelBuffer, labelOffset, labelLength);
} catch (AeronException e) {
if (!e.getMessage().startsWith("failed to write")) throw e;
// retry with exponential backoff while driver is active
} Prevention
- Create counters lazily or in small batches, not in hot init loops
- Keep counter keys and labels short
- Ensure driver is consuming before counter-heavy instrumentation starts
- Monitor driver GC pauses that stall command draining
- Retry transient claim failures instead of crashing instrumentation
When it happens
Trigger: Calling Aeron.addCounter(name, keyBuffer, keyOffset, keyLength, labelBuffer, labelOffset, labelLength) (or via counter factory) when the command ring is full — driver not consuming, stalled, or a burst of counter allocations exceeded drain rate. Very large key/label lengths increase the space needed and make the failure more likely.
Common situations: Instrumentation code allocating hundreds of counters in a loop at startup while the driver is still initializing; driver process crashed; oversized counter labels approaching allocation limits filling the ring quickly.
Related errors
- failed to write remove counter command
- failed to write add rcv destination command
- failed to write remove rcv destination 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/673af091b78b63cf.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-client/src/main/java/io/aeron/DriverProxy.java:386
* @param labelOffset offset at which the label begins.
* @param labelLength length in bytes for the label.
* @return the correlation id for the command.
*/
public long addCounter(
final int typeId,
final DirectBuffer keyBuffer,
final int keyOffset,
final int keyLength,
final DirectBuffer labelBuffer,
final int labelOffset,
final int labelLength)
{
final long correlationId = toDriverCommandBuffer.nextCorrelationId();
final int length = CounterMessageFlyweight.computeLength(keyLength, labelLength);
final int index = toDriverCommandBuffer.tryClaim(ADD_COUNTER, length);
if (index < 0)
{
throw new AeronException("failed to write add counter command");
}
counterMessageFlyweight
.wrap(toDriverCommandBuffer.buffer(), index)
.keyBuffer(keyBuffer, keyOffset, keyLength)
.labelBuffer(labelBuffer, labelOffset, labelLength)
.typeId(typeId)
.clientId(clientId)
.correlationId(correlationId);
toDriverCommandBuffer.commit(index);
return correlationId;
}
/**
* Add a new counter with a type id and label, the key will be blank.
*View on GitHub (pinned to 6d60124e15)