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

  1. Check the media driver is running and consuming commands before allocating counters
  2. Retry addCounter with backoff — the claim failure is transient if the driver is draining
  3. Reduce the burst rate of counter creation; create counters lazily or in stages
  4. Keep counter key/label sizes small to reduce required claim size
  5. 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

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


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)