aeron-io/aeron · error · IllegalStateException

Counter not allocated: id=

Error message

Counter not allocated: id=

What it means

The ReadableCounter constructor verifies via countersReader.getCounterState(counterId) that the counter is in RECORD_ALLOCATED state and throws IllegalStateException otherwise. Counters in an Aeron CountersManager can be unallocated, reclaimed, or in transition, so reading a counter that no longer (or never did) exist fails fast here.

Solutions

  1. Check countersReader.getCounterState(counterId) == CountersReader.RECORD_ALLOCATED before constructing
  2. Catch IllegalStateException and re-resolve the counterId from the counters labels
  3. Refresh the counters snapshot after a driver restart instead of reusing old ids

Example fix

// before
ReadableCounter counter = new ReadableCounter(countersReader, registrationId, counterId);
// after
if (countersReader.getCounterState(counterId) == CountersReader.RECORD_ALLOCATED)
{
    ReadableCounter counter = new ReadableCounter(countersReader, registrationId, counterId);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (countersReader.getCounterState(counterId) != CountersReader.RECORD_ALLOCATED) { /* do not construct */ }

Type guard

null

Try / catch

try { ReadableCounter c = new ReadableCounter(countersReader, registrationId, counterId); }
catch (IllegalStateException e) { /* re-resolve counter id from labels */ }

Prevention

When it happens

Trigger: Constructing ReadableCounter with a counterId that is RECORD_RECLAIMED, RECORD_UNUSED, or otherwise not RECORD_ALLOCATED — typically a stale id from a driver that has since freed the counter.

Common situations: Monitoring a driver that restarted and reallocated counters with different ids; holding a ReadableCounter across a media driver shutdown/restart; racing counter allocation vs. reader construction in Aeron-stat-style tooling.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at aeron-client/src/main/java/io/aeron/status/ReadableCounter.java:52

    private final UnsafeBuffer valueBuffer;
    private final long registrationId;
    private final int counterId;
    private volatile boolean isClosed = false;

    /**
     * Construct a view of an existing counter.
     *
     * @param countersReader for getting access to the buffers.
     * @param registrationId assigned by the driver for the counter or {@link Aeron#NULL_VALUE} if not known.
     * @param counterId      for the counter to be viewed.
     * @throws IllegalStateException if the id has for the counter has not been allocated.
     */
    public ReadableCounter(final CountersReader countersReader, final long registrationId, final int counterId)
    {
        final int counterState = countersReader.getCounterState(counterId);
        if (counterState != CountersReader.RECORD_ALLOCATED)
        {
            throw new IllegalStateException("Counter not allocated: id=" + counterId + " state=" + counterState);
        }

        this.countersReader = countersReader;
        this.counterId = counterId;
        this.registrationId = registrationId;

        final AtomicBuffer valuesBuffer = countersReader.valuesBuffer();
        final int counterOffset = CountersReader.counterOffset(counterId);
        valuesBuffer.boundsCheck(counterOffset, SIZE_OF_LONG);

        valueBuffer = new UnsafeBuffer(valuesBuffer, counterOffset, SIZE_OF_LONG);
    }

    /**
     * Construct a view of an existing counter.
     *
     * @param countersReader for getting access to the buffers.
     * @param counterId      for the counter to be viewed.

View on GitHub (pinned to 6d60124e15)