{"record":{"id":"12a53da810116f42","repo":"aeron-io/aeron","slug":"invalid-position-position-does-not-have-frame-alignment","errorCode":null,"errorMessage":"invalid position=${position} does not have frame alignment=${FRAME_ALIGNMENT}","messagePattern":"invalid position=(.+?) does not have frame alignment=(.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"aeron-client/src/main/java/io/aeron/ChannelUriStringBuilder.java","lineNumber":1633,"sourceCode":"    }\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    /**\n     * Set the underlying OS send buffer length.\n     *\n     * @param socketSndbufLength parameter to be passed as SO_SNDBUF value.\n     * @return this for a fluent API.","sourceCodeStart":1615,"sourceCodeEnd":1651,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-client/src/main/java/io/aeron/ChannelUriStringBuilder.java#L1615-L1651","documentation":"Thrown by ChannelUriStringBuilder's position setter (used when building channel URIs with a starting position, e.g. for term-buffer parameters). Aeron requires every publication position to be aligned to the frame alignment boundary (32 bytes, FRAME_ALIGNMENT). The builder rejects any position that is negative or not a multiple of FRAME_ALIGNMENT because such a position cannot correspond to a valid frame boundary in the log buffer.","triggerScenarios":"Calling ChannelUriStringBuilder.initialPosition(long position, int initialTermId, int termLength) (or the position-taking overload) with a position that is not divisible by 32 (FRAME_ALIGNMENT).","commonSituations":"Resuming a publication/subscription from a recorded position where the recorded value was the raw stream position rather than a frame-aligned one; hand-computed positions using wrong alignment (e.g. term length/2); ports of code from other messaging systems that use unaligned offsets.","solutions":["Round the position down (or use the exact recorded position) to a multiple of FRAME_ALIGNMENT (32): position & ~(FRAME_ALIGNMENT - 1).","Verify the source of the position: it must come from a valid frame boundary (e.g. an image position from Aeron), not an arbitrary byte offset.","If you do not need to resume at a specific position, omit the position/initial-term-id parameters entirely and let Aeron assign them."],"exampleFix":"// before\nbuilder.initialPosition(1234L, initialTermId, termLength); // not 32-byte aligned\n// after\nlong aligned = 1234L & ~(32 - 1); // FRAME_ALIGNMENT = 32\nbuilder.initialPosition(aligned, initialTermId, termLength);","handlingStrategy":"validation","validationCode":"static final int FRAME_ALIGNMENT = 32;\nvoid checkInitialPosition(long position) {\n    if (position < 0 || (position & (FRAME_ALIGNMENT - 1)) != 0) {\n        throw new IllegalArgumentException(\"position must be non-negative and a multiple of \" + FRAME_ALIGNMENT + \": \" + position);\n    }\n}","typeGuard":"boolean isFrameAligned(long position) { return position >= 0 && (position & (32 - 1)) == 0; }","tryCatchPattern":"try {\n    builder.initialPosition(position, initialTermId, termLength);\n} catch (IllegalArgumentException e) {\n    long aligned = Math.max(0, position & ~(32 - 1));\n    builder.initialPosition(aligned, initialTermId, termLength);\n}","preventionTips":["Only use positions obtained from Aeron APIs (image positions, recording positions) — these are always frame-aligned.","Align any computed position down to the 32-byte FRAME_ALIGNMENT before passing it.","Add an assertion on position alignment in your configuration-loading code."],"tags":["aeron","channel-uri","alignment","illegal-argument"],"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"}