{"record":{"id":"d504cd88ec1ff697","repo":"aeron-io/aeron","slug":"channel-media-type-mismatch-when-using-control-mode-response","errorCode":null,"errorMessage":"Channel media type mismatch. When using `control-mode=response`, the `replayChannel` media type must match the media type for the archive control channel.","messagePattern":"Channel media type mismatch\\. When using `control-mode=response`, the `replayChannel` media type must match the media type for the archive control channel\\.","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/client/PersistentSubscription.java","lineNumber":1734,"sourceCode":"            {\n                throw new ConfigurationException(\"invalid recordingId \" + recordingId);\n            }\n\n            if (FROM_LIVE > startPosition)\n            {\n                throw new ConfigurationException(\"invalid startPosition \" + startPosition);\n            }\n\n            final ChannelUri replayChannelUri = ChannelUri.parse(replayChannel);\n\n            if (replayChannelUri.hasControlModeResponse())\n            {\n                final String controlRequestChannel = aeronArchiveContext.controlRequestChannel();\n                if (null != controlRequestChannel &&\n                    !replayChannelUri.isIpc() == ChannelUri.parse(controlRequestChannel).isIpc()\n                )\n                {\n                    throw new ConfigurationException(\n                        \"Channel media type mismatch. \" +\n                            \"When using `control-mode=response`, the `replayChannel` media type must match the media\" +\n                            \" type for the archive control channel.\"\n                    );\n                }\n            }\n\n            replayChannelUri.put(CommonContext.REJOIN_PARAM_NAME, \"false\");\n\n            replayChannel = replayChannelUri.toString();\n\n            if (null == aeron)\n            {\n                final Aeron.Context aeronCtx = new Aeron.Context()\n                    .clientName(\"PersistentSubscription\")\n                    .subscriberErrorHandler(RethrowingErrorHandler.INSTANCE)\n                    .useConductorAgentInvoker(true);\n                if (null != aeronDirectoryName)","sourceCodeStart":1716,"sourceCodeEnd":1752,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/client/PersistentSubscription.java#L1716-L1752","documentation":"When the replayChannel URI includes control-mode=response, the replay channel doubles as an archive control-response channel. conclude() compares its media type (IPC vs network) against the archive control request channel; a mismatch (e.g. replay over UDP while archive control uses IPC) would make response subscriptions unusable, so a ConfigurationException is thrown.","triggerScenarios":"Setting replayChannel to a URI containing '|control-mode=response' whose transport (ipc vs udp/tcp) differs from aeronArchiveContext.controlRequestChannel(). E.g. replayChannel=\"aeron:ipc?control-mode=response\" while archive control is aeron:udp?..., or vice versa.","commonSituations":"Copying a shared-memory (ipc) archive config into a network deployment (or the reverse); manually adding control-mode=response for streaming-connection replay but on a different transport; container/host boundary changes the archive control channel default.","solutions":["Make the replayChannel transport match the archive control channel: if controlRequestChannel is udp, use aeron:udp in replayChannel (and vice versa).","Remove control-mode=response from the replayChannel if you do not need the replay stream to carry archive control responses.","Align aeronArchiveContext.controlRequestChannel() with your intended transport so both sides agree."],"exampleFix":"// before\narchiveCtx.controlRequestChannel(\"aeron:udp?endpoint=localhost:8010\");\nctx.replayChannel(\"aeron:ipc?control-mode=response\"); // ipc vs udp mismatch\nctx.conclude(); // throws: Channel media type mismatch\n\n// after\narchiveCtx.controlRequestChannel(\"aeron:udp?endpoint=localhost:8010\");\nctx.replayChannel(\"aeron:udp?endpoint=localhost:10001|control-mode=response\");","handlingStrategy":"validation","validationCode":"ChannelUri replayUri = ChannelUri.parse(replayChannel);\nif (replayUri.hasControlModeResponse() &&\n    replayUri.isIpc() != ChannelUri(archiveCtx.controlRequestChannel()).isIpc()) {\n    throw new IllegalArgumentException(\"replayChannel transport must match archive control channel when control-mode=response\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    ctx.conclude();\n} catch (ConfigurationException e) {\n    // rebuild replayChannel URI with matching transport\n}","preventionTips":["Derive the replayChannel transport from the archive control channel rather than hardcoding ipc or udp.","Only add control-mode=response when the replay stream must serve as a control-response channel."],"tags":["aeron-archive","configuration","channel-uri","mismatch"],"backgroundTag":"conflicting-config-options","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"}