{"record":{"id":"5b6444a2cb7fe87a","repo":"aeron-io/aeron","slug":"termoffset-termoffset-must-be-a-multiple-of-frame-alignment","errorCode":null,"errorMessage":"termOffset=<termOffset> must be a multiple of FRAME_ALIGNMENT: channel=<channelUri>","messagePattern":"termOffset=<termOffset> must be a multiple of FRAME_ALIGNMENT: channel=<channelUri>","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"aeron-driver/src/main/java/io/aeron/driver/SubscriptionParams.java","lineNumber":97,"sourceCode":"                throw new IllegalArgumentException(\"params must be used as a complete set: \" +\n                    INITIAL_TERM_ID_PARAM_NAME + \" \" +\n                    TERM_ID_PARAM_NAME + \" \" +\n                    TERM_OFFSET_PARAM_NAME + \" channel=\" + channelUri);\n            }\n\n            params.initialTermId = Integer.parseInt(initialTermIdStr);\n            params.termId = Integer.parseInt(termIdStr);\n            params.termOffset = Integer.parseInt(termOffsetStr);\n\n            if (params.termOffset < 0 || params.termOffset > LogBufferDescriptor.TERM_MAX_LENGTH)\n            {\n                throw new IllegalArgumentException(\n                    TERM_OFFSET_PARAM_NAME + \"=\" + params.termOffset + \" out of range: channel=\" + channelUri);\n            }\n\n            if (!FrameDescriptor.isFrameAligned(params.termOffset))\n            {\n                throw new IllegalArgumentException(\n                    TERM_OFFSET_PARAM_NAME + \"=\" + params.termOffset +\n                    \" must be a multiple of FRAME_ALIGNMENT: channel=\" + channelUri);\n            }\n\n            if (params.termId - params.initialTermId < 0)\n            {\n                throw new IllegalStateException(\n                    \"difference greater than 2^31 - 1: \" + INITIAL_TERM_ID_PARAM_NAME + \"=\" +\n                    params.initialTermId + \" when \" + TERM_ID_PARAM_NAME + \"=\" + params.termId + \" channel=\" +\n                    channelUri);\n            }\n\n            params.hasJoinPosition = true;\n        }\n\n        final String reliableStr = channelUri.get(RELIABLE_STREAM_PARAM_NAME);\n        params.isReliable = null != reliableStr ? \"true\".equals(reliableStr) : context.reliableStream();\n","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-driver/src/main/java/io/aeron/driver/SubscriptionParams.java#L79-L115","documentation":"Aeron data frames are aligned to FRAME_ALIGNMENT (32 bytes); a subscription's explicit term-offset must be frame-aligned so the subscriber can start on a frame boundary. Unaligned offsets are rejected with IllegalArgumentException.","triggerScenarios":"Subscription URI with term-offset not a multiple of 32, e.g. term-offset=33 or term-offset=100.","commonSituations":"Deriving the offset from arbitrary positions recorded by hand; computing offsets with non-power-of-two arithmetic; typos in recorded values.","solutions":["Round the offset down to a multiple of 32: termOffset &= ~(FrameDescriptor.FRAME_ALIGNMENT - 1).","Record offsets programmatically (e.g. from image.position()) so they are always aligned.","Use a power-of-two-friendly computation like position & (termLength - 1) then align."],"exampleFix":"// before\nint termOffset = recordedPosition % termLength; // may be unaligned\n// after\nint termOffset = (int)(recordedPosition & (termLength - 1)) & ~(FrameDescriptor.FRAME_ALIGNMENT - 1);","handlingStrategy":"validation","validationCode":"termOffset &= ~(FrameDescriptor.FRAME_ALIGNMENT - 1); // align down to 32 bytes before building the URI","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always align offsets to FRAME_ALIGNMENT (32) before use.","Record resume positions programmatically rather than by hand."],"tags":["aeron","subscription","alignment","config"],"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-16T04:17:20.429Z"}