{"record":{"id":"c750fd47babf88af","repo":"aeron-io/aeron","slug":"replaymerge-no-progress-state-state-activetransportcount","errorCode":null,"errorMessage":"ReplayMerge no progress: state=<state>, activeTransportCount=<transportCount>","messagePattern":"ReplayMerge no progress: state=<state>, activeTransportCount=<transportCount>","errorType":"exception","errorClass":"TimeoutException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/client/ReplayMerge.java","lineNumber":581,"sourceCode":"    private boolean shouldAddLiveDestination(final long position)\n    {\n        return !isLiveAdded &&\n            (nextTargetPosition - position) <= Math.min(image.termBufferLength() >> 2, LIVE_ADD_MAX_WINDOW);\n    }\n\n    private boolean shouldStopAndRemoveReplay(final long position)\n    {\n        return isLiveAdded &&\n            (nextTargetPosition - position) <= REPLAY_REMOVE_THRESHOLD &&\n            image.activeTransportCount() >= 2;\n    }\n\n    private void checkProgress(final long nowMs)\n    {\n        if (nowMs > (timeOfLastProgressMs + mergeProgressTimeoutMs))\n        {\n            final int transportCount = null != image ? image.activeTransportCount() : 0;\n            throw new TimeoutException(\n                \"ReplayMerge no progress: state=\" + state + \", activeTransportCount=\" + transportCount);\n        }\n\n        if (NULL_VALUE == activeCorrelationId &&\n            (nowMs > (timeOfLastScheduledArchivePollMs + ARCHIVE_POLL_INTERVAL_MS)))\n        {\n            timeOfLastScheduledArchivePollMs = nowMs;\n            pollForResponse(archive, NULL_VALUE);\n        }\n    }\n\n    private static boolean pollForResponse(final AeronArchive archive, final long correlationId)\n    {\n        final ControlResponsePoller poller = archive.controlResponsePoller();\n\n        final int pollCount = poller.poll();\n        if (poller.isPollComplete())\n        {","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/client/ReplayMerge.java#L563-L599","documentation":"ReplayMerge tracks progress; if no position or state progress is made within mergeProgressTimeoutMs, checkProgress throws a TimeoutException naming the merge state and active transport count. This prevents a wedged merge (e.g. lost replay, unreachable live destination) from hanging forever.","triggerScenarios":"nowMs exceeds timeOfLastProgressMs + mergeProgressTimeoutMs with no position advance — stalled replay delivery, unreachable live destination, or archive not sending data.","commonSituations":"Firewall blocking the replay or live UDP destinations; archive overloaded; mergeProgressTimeoutMs set too small for slow catchup on high-latency links.","solutions":["Verify the replay and live destination endpoints are reachable (ports open, correct host)","Increase the mergeProgressTimeoutMs constructor parameter on slow networks","Check the archive is actively replaying (logs, recording position advancing)","Restart the ReplayMerge after diagnosing the stall"],"exampleFix":"// before\nnew ReplayMerge(archive, sub, replayChannel, replayDest, liveDest, recordingId, 0, 5_000, ctx.epochClock(), 1024, \"\");\n// after: generous timeout\nnew ReplayMerge(archive, sub, replayChannel, replayDest, liveDest, recordingId, 0, 60_000, ctx.epochClock(), 1024, \"\");","handlingStrategy":"retry","validationCode":"// pre-check connectivity to replay/live destinations before merging\nif (!isEndpointReachable(replayDest) || !isEndpointReachable(liveDest)) { awaitNetwork(); }","typeGuard":null,"tryCatchPattern":"catch (TimeoutException e) { if (e.getMessage().startsWith(\"ReplayMerge no progress\")) { retryWithBackoff(() -> newReplayMerge()); } }","preventionTips":["Set mergeProgressTimeoutMs generously for slow/high-latency networks","Verify UDP endpoints (firewalls, ports) before starting a merge","Log state and transportCount from the exception to diagnose stalls"],"tags":["timeout","replay-merge","network","stall"],"backgroundTag":"request-timeout","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"}