{"record":{"id":"5109010fb1235332","repo":"aeron-io/aeron","slug":"invalid-position-position-0","errorCode":null,"errorMessage":"invalid position=${position} < 0","messagePattern":"invalid position=(.+?) < 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"aeron-client/src/main/java/io/aeron/ChannelUriStringBuilder.java","lineNumber":1629,"sourceCode":"     */\n    public Boolean spiesSimulateConnection()\n    {\n        return ssc;\n    }\n\n    /**\n     * Initialise a channel for restarting a publication at a given position.\n     *\n     * @param position      at which the publication should be started.\n     * @param initialTermId what which the stream would start.\n     * @param termLength    for the stream.\n     * @return this for a fluent API.\n     */\n    public ChannelUriStringBuilder initialPosition(final long position, final int initialTermId, final int termLength)\n    {\n        if (position < 0)\n        {\n            throw new IllegalArgumentException(\"invalid position=\" + position + \" < 0\");\n        }\n        if (0 != (position & (FRAME_ALIGNMENT - 1)))\n        {\n            throw new IllegalArgumentException(\n                \"invalid position=\" + position + \" does not have frame alignment=\" + FRAME_ALIGNMENT);\n        }\n\n        final int bitsToShift = LogBufferDescriptor.positionBitsToShift(termLength);\n\n        this.initialTermId = initialTermId;\n        this.termId = LogBufferDescriptor.computeTermIdFromPosition(position, bitsToShift, initialTermId);\n        this.termOffset = (int)(position & (termLength - 1));\n        this.termLength = termLength;\n\n        return this;\n    }\n\n    /**","sourceCodeStart":1611,"sourceCodeEnd":1647,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-client/src/main/java/io/aeron/ChannelUriStringBuilder.java#L1611-L1647","documentation":"ChannelUriStringBuilder.initialPosition(position, initialTermId, termLength) computes the term offset from the given absolute position and rejects negative positions outright. Positions in Aeron are non-negative 64-bit stream offsets; a negative value indicates corrupted arithmetic or a wrongly decoded position. (A second check in the same method also requires frame alignment of 32 bytes.)","triggerScenarios":"Calling initialPosition(-1, termId, termLength), or passing a position computed by subtraction that underflowed, or one decoded from a packed long that lost its sign handling.","commonSituations":"Restoring a publication/replay position from persistent state where the stored value was corrupted; subtracting a larger position from a smaller one; casting unsigned 64-bit values above Long.MAX_VALUE to a negative long.","solutions":["Fix the source of the position so it is never negative before calling initialPosition","Validate the position and reject/repair negative values: if (position < 0) throw or reset to 0","Also ensure the position is a multiple of FRAME_ALIGNMENT (32) or the next check will throw","Use values from Aeron's own position APIs (publication.position(), image.position()) which are guaranteed non-negative"],"exampleFix":"// before\nlong pos = recordedPosition - basePosition; // can underflow\nbuilder.initialPosition(pos, termId, termLength);\n// after\nlong pos = Math.max(0, recordedPosition - basePosition);\npos &= ~(32 - 1); // align to FRAME_ALIGNMENT\nbuilder.initialPosition(pos, termId, termLength);","handlingStrategy":"validation","validationCode":"int FRAME_ALIGNMENT = 32;\nif (position < 0) throw new IllegalArgumentException(\"position must be >= 0\");\nif ((position & (FRAME_ALIGNMENT - 1)) != 0) throw new IllegalArgumentException(\"position must be 32-byte aligned\");","typeGuard":null,"tryCatchPattern":"try { builder.initialPosition(pos, termId, termLength); } catch (IllegalArgumentException e) { /* clamp/recompute pos */ }","preventionTips":["Persist positions from Aeron APIs (publication.position()) which are non-negative and aligned","Guard against underflow when computing relative positions","Align positions to 32 bytes before calling initialPosition"],"tags":["aeron","uri-validation","argument-out-of-range"],"backgroundTag":"value-out-of-range","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"}