{"record":{"id":"82b12d874f051819","repo":"aeron-io/aeron","slug":"unexpected-recording-stop-during-catchup-position-position","errorCode":null,"errorMessage":"unexpected recording stop during catchup: position=<position>","messagePattern":"unexpected recording stop during catchup: position=<position>","errorType":"exception","errorClass":"ClusterEvent","httpStatus":null,"severity":"error","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModuleAgent.java","lineNumber":1984,"sourceCode":"            }\n        }\n    }\n\n    void catchupInitiated(final long nowNs)\n    {\n        timeOfLastAppendPositionUpdateNs = nowNs;\n        timeOfLastAppendPositionSendNs = nowNs;\n    }\n\n    int catchupPoll(final long limitPosition, final long nowNs)\n    {\n        int workCount = 0;\n\n        if (ConsensusModule.State.ACTIVE == state || ConsensusModule.State.SUSPENDED == state)\n        {\n            if (null == appendPosition)\n            {\n                throw new ClusterEvent(\n                    \"unexpected recording stop during catchup: position=\" + logAdapter.position());\n            }\n\n            final long currentAppendPosition = appendPosition.get();\n            final int fragments = logAdapter.poll(min(currentAppendPosition, limitPosition));\n            workCount += fragments;\n            if (0 == fragments && logAdapter.isImageClosed())\n            {\n                throw new ClusterEvent(\n                    \"unexpected image close during catchup: position=\" + logAdapter.position());\n            }\n\n            workCount += updateFollowerPosition(\n                election.leader().publication(),\n                nowNs,\n                leadershipTermId,\n                currentAppendPosition,\n                APPEND_POSITION_FLAG_CATCHUP);","sourceCodeStart":1966,"sourceCodeEnd":2002,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModuleAgent.java#L1966-L2002","documentation":"During log catch-up the follower tracks how far the recording has been appended via appendPosition. If the recording stops (appendPosition becomes null) while the node is still ACTIVE or SUSPENDED and catching up, the agent throws ClusterEvent because catch-up can no longer make progress.","triggerScenarios":"In catchup(), appendPosition is null (recording stopped / recording signal lost) while state is ACTIVE or SUSPENDED, meaning the archive recording being followed terminated before the node caught up.","commonSituations":"Leader/recording stopped while a slow follower was still catching up; archive recording ended prematurely (disk full, archive agent crash); membership change removing the source recording mid-catchup.","solutions":["Ensure the leader keeps recording until all followers complete catch-up (check recording lifecycle and aeron.archive settings).","Investigate archive agent logs for why the recording stopped (disk full, archive crash).","Retry election/catch-up — the cluster will typically re-elect and request the recording again.","Increase archive storage capacity and monitor recording continuity on the leader."],"exampleFix":"// before: leader stops recording as soon as it commits\n// after: leader retains recording until min follower position >= recording end\nif (minFollowerPosition < recordingStopPosition) { keepRecording(); }","handlingStrategy":"retry","validationCode":"// before catchup\nif (!archive.isRecordingActive(recordingId)) { triggerElectionRestart(); }","typeGuard":null,"tryCatchPattern":"try { agent.doWork(); } catch (ClusterEvent e) { if (e.getMessage().contains(\"unexpected recording stop during catchup\")) { restartCatchupOrElection(); } else { throw e; } }","preventionTips":["Provision enough archive disk so recordings never end early.","Keep the leader recording until every follower has caught up.","Alert on recording-stop signals while followers are behind."],"tags":["archive","catchup","recording","replication"],"backgroundTag":"unexpected-response-shape","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"}