{"record":{"id":"43853299456b4ae1","repo":"aeron-io/aeron","slug":"joinposition-joinposition-expected-startposition","errorCode":null,"errorMessage":"joinPosition=${joinPosition} expected startPosition=${startPosition}","messagePattern":"joinPosition=(.+?) expected startPosition=(.+?)","errorType":"exception","errorClass":"ClusterException","httpStatus":null,"severity":"warning","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/LogReplay.java","lineNumber":88,"sourceCode":"        {\n            errorHandler.onError(ex);\n        }\n        logAdapter.disconnect(errorHandler);\n        CloseHelper.close(errorHandler, logSubscription);\n    }\n\n    int doWork()\n    {\n        int workCount = 0;\n\n        if (null == logAdapter.image())\n        {\n            final Image image = logSubscription.imageBySessionId(logSessionId);\n            if (null != image)\n            {\n                if (image.joinPosition() != startPosition)\n                {\n                    throw new ClusterException(\n                        \"joinPosition=\" + image.joinPosition() + \" expected startPosition=\" + startPosition,\n                        ClusterException.Category.WARN);\n                }\n\n                logAdapter.image(image);\n                consensusModuleAgent.awaitServicesReady(\n                    logSubscription.channel(),\n                    logSubscription.streamId(),\n                    logSessionId,\n                    startPosition,\n                    stopPosition,\n                    true,\n                    Cluster.Role.FOLLOWER);\n\n                workCount += 1;\n            }\n        }\n        else","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/LogReplay.java#L70-L106","documentation":"During log replay, LogReplay.doWork locates the replay Image by session id and asserts its joinPosition equals the expected startPosition for the replay. If the image was joined at a different position the replay would deliver wrong entries, so a WARN-category ClusterException is thrown and the replay fails.","triggerScenarios":"Replaying the log after election/snapshot recovery when the archive image for the log session was joined at a position that differs from the replay startPosition — e.g. the archive recording starts later than the requested replay position, or a stale subscription image is picked up.","commonSituations":"Missing or truncated archive segments so the recording's start position moved forward; racing a new recording image while replaying; misconfigured replay channel/merge in cluster recovery.","solutions":["Verify the archive contains a recording covering the requested replay startPosition (aeron-archive catalog)","Restore from a later snapshot so replay can start from a position the recording actually contains","Ensure the log subscription is bound to the correct log session id and no stale image is reused","Check archive recording start positions vs the cluster's recovery plan (recoveryPlan)"],"exampleFix":"// before: replaying from an arbitrary snapshot position\nreplay(fromPosition);\n// after: use the recovery plan's snapshot/recording positions\nRecoveryPlan plan = archiveClient.buildRecoveryPlan(...);\nreplay(plan.snapshotPosition());","handlingStrategy":"try-catch","validationCode":"if (image.joinPosition() != replayStartPosition) { /* re-plan recovery from snapshot */ }","typeGuard":null,"tryCatchPattern":"try { replay.doWork(); } catch (ClusterException e) { /* WARN category: fall back to a later snapshot */ }","preventionTips":["Ensure archive recordings cover the replay startPosition","Recover from snapshots listed in the recovery plan","Avoid reusing stale log subscription images"],"tags":["aeron-cluster","replay","archive","log-position"],"backgroundTag":"internal-invariant-violation","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"}