{"record":{"id":"7c4264b9b6a6c37c","repo":"aeron-io/aeron","slug":"subscription-uri-must-have-control-mode-manual-uri-channel","errorCode":null,"errorMessage":"Subscription URI must have 'control-mode=manual' uri=<channel>","messagePattern":"Subscription URI must have 'control-mode=manual' uri=<channel>","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/client/ReplayMerge.java","lineNumber":133,"sourceCode":"        final String replayChannel,\n        final String replayDestination,\n        final String liveDestination,\n        final long recordingId,\n        final long startPosition,\n        final EpochClock epochClock,\n        final long mergeProgressTimeoutMs)\n    {\n        if (subscription.channel().startsWith(IPC_CHANNEL) ||\n            replayChannel.startsWith(IPC_CHANNEL) ||\n            replayDestination.startsWith(IPC_CHANNEL) ||\n            liveDestination.startsWith(IPC_CHANNEL))\n        {\n            throw new IllegalArgumentException(\"IPC merging is not supported\");\n        }\n\n        if (!subscription.channel().contains(\"control-mode=manual\"))\n        {\n            throw new IllegalArgumentException(\n                \"Subscription URI must have 'control-mode=manual' uri=\" + subscription.channel());\n        }\n\n        this.archive = archive;\n        this.subscription = subscription;\n        this.epochClock = epochClock;\n        this.replayDestination = replayDestination;\n        this.liveDestination = liveDestination;\n        this.recordingId = recordingId;\n        this.startPosition = startPosition;\n        this.mergeProgressTimeoutMs = mergeProgressTimeoutMs;\n\n        replayChannelUri = ChannelUri.parse(replayChannel);\n        replayChannelUri.put(CommonContext.LINGER_PARAM_NAME, \"0\");\n        replayChannelUri.put(CommonContext.EOS_PARAM_NAME, \"false\");\n\n        final String replayEndpoint = ChannelUri.parse(replayDestination).get(ENDPOINT_PARAM_NAME);\n        if (replayEndpoint.endsWith(\":0\"))","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/client/ReplayMerge.java#L115-L151","documentation":"ReplayMerge requires the subscription's channel URI to contain 'control-mode=manual' so the merge can control when the image joins the live destination. If the subscription URI lacks this parameter, the constructor throws IllegalArgumentException with the offending URI.","triggerScenarios":"Calling new ReplayMerge(...) with a subscription created from a URI missing 'control-mode=manual', e.g. 'aeron:udp?endpoint=host:port'.","commonSituations":"Reusing an existing subscription that used automatic control mode; forgetting that ReplayMerge needs manual MDC control; older samples/docs showing plain endpoints.","solutions":["Add 'control-mode=manual' to the subscription URI before creating the subscription and ReplayMerge","Create a fresh subscription with the corrected URI rather than reusing an auto-control-mode one","Verify the URI with ChannelUri to confirm the parameter is present"],"exampleFix":"// before\nSubscription sub = aeron.addSubscription(\"aeron:udp?endpoint=0.0.0.0:2000\", streamId);\n// after\nSubscription sub = aeron.addSubscription(\"aeron:udp?endpoint=0.0.0.0:2000|control-mode=manual\", streamId);","handlingStrategy":"validation","validationCode":"if (!sub.channel().contains(\"control-mode=manual\")) {\n    throw new IllegalArgumentException(\"subscription URI must contain control-mode=manual: \" + sub.channel());\n}","typeGuard":null,"tryCatchPattern":"try { new ReplayMerge(archive, sub, replayChannel, replayDest, liveDest, recordingId, 0); }\ncatch (IllegalArgumentException e) { if (e.getMessage().contains(\"control-mode=manual\")) { recreateSubscriptionWithManualControlMode(); } }","preventionTips":["Add control-mode=manual whenever creating subscriptions intended for ReplayMerge","Check URI parameters with ChannelUri before constructing the merge","Centralize subscription creation in one helper that enforces the parameter"],"tags":["configuration","uri","replay-merge","illegal-argument"],"backgroundTag":"missing-required-config-field","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"}