{"record":{"id":"462b4bde6539237b","repo":"aeron-io/aeron","slug":"cluster-log-must-be-contiguous-for-active-log-event","errorCode":null,"errorMessage":"Cluster log must be contiguous for active log event: expectedPosition=${logPosition} joinPosition=${image.joinPosition()}","messagePattern":"Cluster log must be contiguous for active log event: expectedPosition=(.+?) joinPosition=(.+?)","errorType":"console","errorClass":"ClusterException","httpStatus":null,"severity":"critical","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/service/ClusteredServiceAgent.java","lineNumber":871,"sourceCode":"            CLUSTER_ACTION_FLAGS_DEFAULT;\n\n        final String channel = new ChannelUriStringBuilder(activeLog.channel)\n            .alias(subscriptionAlias)\n            .build();\n\n        Subscription logSubscription = aeron.addSubscription(channel, activeLog.streamId);\n        try\n        {\n            final Image image = awaitImage(activeLog.sessionId, logSubscription);\n            if (image.joinPosition() != logPosition)\n            {\n                throw new ClusterException(\"Cluster log must be contiguous for joining image: \" +\n                    \"expectedPosition=\" + logPosition + \" joinPosition=\" + image.joinPosition());\n            }\n\n            if (activeLog.logPosition != logPosition)\n            {\n                throw new ClusterException(\"Cluster log must be contiguous for active log event: \" +\n                    \"expectedPosition=\" + logPosition + \" eventPosition=\" + activeLog.logPosition);\n            }\n\n            logAdapter.image(image);\n            logAdapter.maxLogPosition(activeLog.maxLogPosition);\n            logSubscription = null;\n\n            final long id = ackId++;\n            while (!consensusModuleProxy.ack(activeLog.logPosition, clusterTime, id, NULL_VALUE, serviceId))\n            {\n                idle();\n            }\n        }\n        finally\n        {\n            CloseHelper.quietClose(logSubscription);\n        }\n","sourceCodeStart":853,"sourceCodeEnd":889,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/service/ClusteredServiceAgent.java#L853-L889","documentation":"Thrown as ClusterException when the active log event for the subscribed image reports a logPosition that differs from the expected position the container recovered to. This is the counterpart of the joining-image check: even if the image joinPosition matched, the actual active log event must confirm the same expected position or the log is not contiguous.","triggerScenarios":"A LogAdapter activeLog event arrives with activeLog.logPosition != the recovered logPosition; racing/reordered log events after election; stale active log event from a previous term delivered to the recovering container.","commonSituations":"Cluster member rejoined while the log advanced past its recovery point without proper catch-up; election edge cases in mixed clusters; container restored from a snapshot whose position is behind the currently active log.","solutions":["Take a new cluster snapshot so all members restore to the current log position","Verify cluster consensus state (leadership term, log position) is consistent across members","Check for clock/election misconfiguration and ensure all members run the same Aeron version","Restart the container so it re-runs recovery with the correct recovery plan"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (activeLog.logPosition != expectedLogPosition) {\n    throw new IllegalStateException(\"active log event mismatch: \" + activeLog.logPosition + \" != \" + expectedLogPosition);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Take snapshots before planned restarts so recovery positions match the live log","Avoid injecting stale log events; restart the container to re-run recovery cleanly","Verify election/quorum health before joining a recovering node"],"tags":["aeron","cluster","consistency","election"],"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-19T12:17:13.211Z"}