{"record":{"id":"46d26481594fe3cc","repo":"aeron-io/aeron","slug":"recordingid-recordingid-is-less-than-or-equal-to-the-last","errorCode":null,"errorMessage":"recordingId \" + recordingId + \" is less than or equal to the last recordingId \" + index[nextPosition - 2]","messagePattern":"recordingId \" \\+ recordingId \\+ \" is less than or equal to the last recordingId \" \\+ index\\[nextPosition - 2\\]","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/CatalogIndex.java","lineNumber":57,"sourceCode":"     *\n     * @param recordingId               to add.\n     * @param recordingDescriptorOffset for the given id.\n     * @throws IllegalArgumentException if {@code recordingId < 0 || recordingDescriptorOffset < 0}.\n     * @throws IllegalArgumentException if {@code recordingId} is less than or equal to the last recording id added,\n     *                                  i.e. {@code recordingId} must always increase.\n     */\n    void add(final long recordingId, final long recordingDescriptorOffset)\n    {\n        ensurePositive(recordingId, \"recordingId\");\n        ensurePositive(recordingDescriptorOffset, \"recordingDescriptorOffset\");\n\n        final int nextPosition = count << 1;\n        long[] index = this.index;\n        if (nextPosition > 0)\n        {\n            if (recordingId <= index[nextPosition - 2])\n            {\n                throw new IllegalArgumentException(\"recordingId \" + recordingId +\n                    \" is less than or equal to the last recordingId \" + index[nextPosition - 2]);\n            }\n            if (nextPosition == index.length)\n            {\n                index = expand(index);\n                this.index = index;\n            }\n        }\n        index[nextPosition] = recordingId;\n        index[nextPosition + 1] = recordingDescriptorOffset;\n\n        count++;\n    }\n\n    /**\n     * Remove given recording id from the index.\n     *\n     * @param recordingId to remove.","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/CatalogIndex.java#L39-L75","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Skip or de-duplicate recordingIds that are <= the last indexed id before calling add","Ensure recordingIds come from Catalog.addRecording / the catalog's monotonic counter, not hand-assigned values","Rebuild the index from a clean catalog snapshot rather than merging an old index on top","If restoring from backup, remove duplicate catalog entries before indexing"],"exampleFix":"// before\nfor (entry : restoredEntries) { index.add(entry.recordingId, entry.position); }\n// after\nlong lastId = Long.MIN_VALUE;\nfor (entry : restoredEntries) {\n    if (entry.recordingId > lastId) {\n        index.add(entry.recordingId, entry.position);\n        lastId = entry.recordingId;\n    }\n}","handlingStrategy":"validation","validationCode":"if (recordingId <= lastIndexedRecordingId) {\n    throw new IllegalArgumentException(\"recordingId \" + recordingId + \" must exceed \" + lastIndexedRecordingId);\n}","typeGuard":null,"tryCatchPattern":"try {\n    index.add(recordingId, position);\n} catch (IllegalArgumentException e) {\n    log.warn(\"skipping duplicate/out-of-order recordingId: \" + recordingId);\n}","preventionTips":["Always obtain recordingIds from the catalog's monotonic counter (Catalog.addRecording)","De-duplicate entries before rebuilding a catalog index","Never merge index data from an older backup on top of newer entries","Verify recordingIds are strictly increasing before indexing"],"tags":["aeron-archive","catalog-index","argument-validation","ordering"],"backgroundTag":"invalid-argument-value","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}