aeron-io/aeron · error · IllegalArgumentException

recordingId " + recordingId + " is less than or equal to…

Error message

recordingId " + recordingId + " is less than or equal to the last recordingId " + index[nextPosition - 2]

What it means

Thrown by CatalogIndex.add when a new recordingId is not strictly greater than the last recordingId already in the index. The index is a sorted array of (recordingId, position) pairs and requires strictly increasing recordingIds, so a duplicate or out-of-order add is rejected with IllegalArgumentException.

Solutions

  1. Skip or de-duplicate recordingIds that are <= the last indexed id before calling add
  2. Ensure recordingIds come from Catalog.addRecording / the catalog's monotonic counter, not hand-assigned values
  3. Rebuild the index from a clean catalog snapshot rather than merging an old index on top
  4. If restoring from backup, remove duplicate catalog entries before indexing

Example fix

// before
for (entry : restoredEntries) { index.add(entry.recordingId, entry.position); }
// after
long lastId = Long.MIN_VALUE;
for (entry : restoredEntries) {
    if (entry.recordingId > lastId) {
        index.add(entry.recordingId, entry.position);
        lastId = entry.recordingId;
    }
}
Defensive patterns

Strategy: validation

Validate before calling

if (recordingId <= lastIndexedRecordingId) {
    throw new IllegalArgumentException("recordingId " + recordingId + " must exceed " + lastIndexedRecordingId);
}

Try / catch

try {
    index.add(recordingId, position);
} catch (IllegalArgumentException e) {
    log.warn("skipping duplicate/out-of-order recordingId: " + recordingId);
}

Prevention

When it happens

Trigger: Adding a recording whose id is <= the last indexed id — e.g. replaying catalog entries into an existing index, restoring from a backup that duplicates entries, or assigning non-monotonic recordingIds from custom tooling.

Common situations: Rebuilding a catalog index over an already-indexed catalog, double-appending entries after a partial failure, or external tools inserting recordings with reused/rolled-back ids.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at aeron-archive/src/main/java/io/aeron/archive/CatalogIndex.java:57

     *
     * @param recordingId               to add.
     * @param recordingDescriptorOffset for the given id.
     * @throws IllegalArgumentException if {@code recordingId < 0 || recordingDescriptorOffset < 0}.
     * @throws IllegalArgumentException if {@code recordingId} is less than or equal to the last recording id added,
     *                                  i.e. {@code recordingId} must always increase.
     */
    void add(final long recordingId, final long recordingDescriptorOffset)
    {
        ensurePositive(recordingId, "recordingId");
        ensurePositive(recordingDescriptorOffset, "recordingDescriptorOffset");

        final int nextPosition = count << 1;
        long[] index = this.index;
        if (nextPosition > 0)
        {
            if (recordingId <= index[nextPosition - 2])
            {
                throw new IllegalArgumentException("recordingId " + recordingId +
                    " is less than or equal to the last recordingId " + index[nextPosition - 2]);
            }
            if (nextPosition == index.length)
            {
                index = expand(index);
                this.index = index;
            }
        }
        index[nextPosition] = recordingId;
        index[nextPosition + 1] = recordingDescriptorOffset;

        count++;
    }

    /**
     * Remove given recording id from the index.
     *
     * @param recordingId to remove.

View on GitHub (pinned to 6d60124e15)