aeron-io/aeron · error · IllegalArgumentException
counter id is negative
Error message
counter id <counterId> is negative
What it means
validateCounterId in AeronCounters rejects any negative counterId before touching the metadata buffer. Counter ids index into the counters metadata file, so a negative id is structurally invalid. This guards the metadata-offset arithmetic (counterId * METADATA_LENGTH) from producing unsafe offsets.
Solutions
- Check counterId >= 0 before calling the API, or initialize the id to a valid allocated value.
- Replace -1 sentinels with Optional<Integer> or an explicit 'unallocated' boolean.
- Log and inspect where the negative id originates — likely an uninitialized field or bad decode from a wire/IPC message.
Example fix
// before
int counterId = -1;
aeron.counters().updateLabel(counterId, "x");
// after
if (counterId >= 0) {
aeron.counters().updateLabel(counterId, "x");
} Defensive patterns
Strategy: validation
Validate before calling
if (counterId < 0) throw new IllegalArgumentException("counterId must be >= 0: " + counterId); Try / catch
try {
aeronCounters.updateLabel(counterId, label);
} catch (IllegalArgumentException e) {
log.warn("invalid counter id", e);
} Prevention
- Initialize counterId fields to 0 or use Optional instead of -1 sentinels
- Validate ids decoded from IPC/network messages before use
- Guard against integer overflow when computing ids
When it happens
Trigger: Passing a negative int as counterId to any AeronCounters public API that validates the id (e.g. label updates, metadata access). Typically from an uninitialized field, a sentinel like -1, or integer underflow when computing the id.
Common situations: Using -1 as a 'no counter yet' sentinel and forgetting to check it; reading counterId from a C/other-language client that used an unsigned/invalid value; arithmetic overflow producing a negative id.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- counter id out of range: 0 - maxCounterId=
- counter id is not allocated, state
- initialCapacity outside range 0
- limit outside range: capacity=
- key length out of bounds
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/4b1651565782df33.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-client/src/main/java/io/aeron/AeronCounters.java:1662
* @param referenceId to set for the counter.
* @see CountersReader#getCounterReferenceId(int)
* @since 1.49.0
*/
public static void setReferenceId(
final AtomicBuffer metaDataBuffer, final AtomicBuffer valuesBuffer, final int counterId, final long referenceId)
{
Objects.requireNonNull(metaDataBuffer);
Objects.requireNonNull(valuesBuffer);
validateCounterId(metaDataBuffer, counterId);
valuesBuffer.putLongRelease(counterOffset(counterId) + REFERENCE_ID_OFFSET, referenceId);
}
private static void validateCounterId(final AtomicBuffer metaDataBuffer, final int counterId)
{
if (counterId < 0)
{
throw new IllegalArgumentException("counter id " + counterId + " is negative");
}
final int maxCounterId = (metaDataBuffer.capacity() / METADATA_LENGTH) - 1;
if (counterId > maxCounterId)
{
throw new IllegalArgumentException(
"counter id " + counterId + " out of range: 0 - maxCounterId=" + maxCounterId);
}
}
}
View on GitHub (pinned to 6d60124e15)