{"record":{"id":"4c7b2010b0a7ecf0","repo":"aeron-io/aeron","slug":"name-cannot-be-negative-value-value","errorCode":null,"errorMessage":"name + \" cannot be negative: value=\" + value","messagePattern":"name \\+ \" cannot be negative: value=\" \\+ value","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/CatalogIndex.java","lineNumber":221,"sourceCode":"        }\n\n        return -1;\n    }\n\n    private static long[] expand(final long[] index)\n    {\n        final int length = index.length;\n        final int entries = length >> 1;\n        final int newLength = (entries + (entries >> 1)) << 1;\n\n        return copyOf(index, newLength);\n    }\n\n    private static void ensurePositive(final long value, final String name)\n    {\n        if (value < 0L)\n        {\n            throw new IllegalArgumentException(name + \" cannot be negative: value=\" + value);\n        }\n    }\n}\n","sourceCodeStart":203,"sourceCodeEnd":225,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/CatalogIndex.java#L203-L225","documentation":"CatalogIndex.ensurePositive throws IllegalArgumentException when a caller passes a negative value for a catalog index operation argument (e.g. recording id, position or offset used by add, remove, or recordingOffset). The Aeron Archive catalog requires non-negative identifiers and offsets, so negative values are rejected up front with the offending name and value in the message.","triggerScenarios":"Calling CatalogIndex.add, remove, or recordingOffset with a negative long argument, typically a recordingId, startPosition, or offset computed from a failed lookup (e.g. -1 sentinel) or an underflowed subtraction.","commonSituations":"Passing a -1 sentinel value returned by a failed recording-id lookup; subtracting positions where the minuend is smaller than the subtrahend; uninitialized long fields defaulted incorrectly; deserializing corrupt control or configuration values.","solutions":["Validate arguments are >= 0 before calling add/remove/recordingOffset and map -1 sentinels to explicit 'not found' handling instead of passing them through","Check arithmetic that produces the value for underflow; clamp or throw a domain-specific error when a computed position/offset goes negative","Log the value and its source at the call site to find where the negative value originates","Verify external inputs (config files, control requests, replay parameters) are parsed and range-checked before reaching the catalog index"],"exampleFix":"// before\nlong offset = stopPosition - startPosition; // can be negative if stop < start\ncatalogIndex.recordingOffset(recordingId, offset);\n// after\nlong offset = stopPosition - startPosition;\nif (offset < 0) { throw new IllegalArgumentException(\"stopPosition < startPosition for recordingId=\" + recordingId); }\ncatalogIndex.recordingOffset(recordingId, offset);","handlingStrategy":"validation","validationCode":"if (recordingId < 0) { throw new IllegalArgumentException(\"recordingId must be non-negative, got \" + recordingId); }\nif (offset < 0) { throw new IllegalArgumentException(\"offset must be non-negative, got \" + offset); }\ncatalogIndex.recordingOffset(recordingId, offset);","typeGuard":"static boolean isNonNegative(long v) { return v >= 0L; }","tryCatchPattern":"try { catalogIndex.remove(recordingId); }\ncatch (IllegalArgumentException e) { if (e.getMessage().contains(\"cannot be negative\")) { /* map to caller error */ } else { throw e; } }","preventionTips":["Never pass -1 sentinel values from failed lookups into catalog index calls","Range-check all recording ids, positions, and offsets at API boundaries","Unit-test subtraction-based position math for underflow","Validate parsed external config/request values before use"],"tags":["java","aeron-archive","illegal-argument","catalog","validation"],"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"}