aeron-io/aeron · error · ClusterException
invalid state counter code
Error message
invalid state counter code: ${code} What it means
ConsensusModule.State.get maps a counter code to a State enum value and rejects codes outside the valid range [0, STATES.length-1] with ClusterException "invalid state counter code". The code comes from the consensus module's status counter, so an out-of-range code means the counter was corrupted or written by an incompatible component.
Solutions
- Verify you read the counter's value, not its registration/counter id, before mapping to State.
- Ensure the Aeron driver and cluster versions match across all components.
- Check that no other process is writing to the consensus module status counter.
- If counters come from a corrupted mark/counters file, stop the node and clear the Aeron directory (aeron.directory.delete.on.start=true) before restart.
Example fix
// before
long code = counter.counterId(); // wrong: id, not value
State state = ConsensusModule.State.get(code);
// after
long code = counter.get(); // actual counter value
if (code >= 0 && code < ConsensusModule.State.values().length)
{
State state = ConsensusModule.State.get(code);
} Defensive patterns
Strategy: validation
Validate before calling
long code = counter.get();
if (code < 0 || code >= ConsensusModule.State.values().length)
{
throw new IllegalStateException("invalid state counter code: " + code);
} Type guard
boolean isValidStateCode(long code)
{
return code >= 0 && code < ConsensusModule.State.values().length;
} Try / catch
try
{
State state = ConsensusModule.State.get(code);
}
catch (ClusterException ex)
{
if (!ex.getMessage().startsWith("invalid state counter code")) throw ex;
// re-read the counter value; check driver/agent version alignment
} Prevention
- Read the counter's value (counter.get()), never its id.
- Use Aeron's CounterListener/inspectors rather than hand-rolled counter parsing.
- Keep driver, client and cluster versions aligned; clear stale Aeron dirs when upgrading.
When it happens
Trigger: Reading the consensus module's status counter (CounterListener / get(code)) where the counter value is negative or greater than the number of defined States (e.g. reading a counter Id instead of its value, or a counter written by a different Aeron version).
Common situations: Application code reading the wrong counter (using counterId as the code); stale/corrupted counters left in a reused Aeron directory; mixing Aeron versions between the media driver and cluster where state encodings differ; agents aggregating counters incorrectly.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid role counter code
- exceeds max key length
- active counter not found
- registration id is not a Counter
- Counter id is not allocated:
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/aeca25477011d707.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModule.java:232
{
return CLOSED;
}
return get(counter.get());
}
/**
* Get the {@link State} corresponding to a particular code.
*
* @param code representing a {@link State}.
* @return the {@link State} corresponding to the provided code.
* @throws ClusterException if the code does not correspond to a valid State.
*/
public static State get(final long code)
{
if (code < 0 || code > (STATES.length - 1))
{
throw new ClusterException("invalid state counter code: " + code);
}
return STATES[(int)code];
}
/**
* Get the current state of the {@link ConsensusModule}.
*
* @param counters to search within.
* @param clusterId to which the allocated counter belongs.
* @return the state of the ConsensusModule or null if not found.
*/
public static State find(final CountersReader counters, final int clusterId)
{
final int counterId = ClusterCounters.find(counters, CONSENSUS_MODULE_STATE_TYPE_ID, clusterId);
if (Aeron.NULL_VALUE != counterId)
{
return State.get(counters.getCounterValue(counterId));View on GitHub (pinned to 6d60124e15)