{"record":{"id":"dc2e2c9d0226eca7","repo":"apache/pulsar","slug":"when-messagerouter-is-set-messageroutingmode","errorCode":null,"errorMessage":"When 'messageRouter' is set, 'messageRoutingMode' should be set as CustomPartition","messagePattern":"When 'messageRouter' is set, 'messageRoutingMode' should be set as CustomPartition","errorType":"exception","errorClass":"PulsarClientException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/ProducerBuilderImpl.java","lineNumber":401,"sourceCode":"     * @return the producer builder implementation instance\n     */\n    public ProducerBuilderImpl<T> initialSubscriptionName(String initialSubscriptionName) {\n        conf.setInitialSubscriptionName(initialSubscriptionName);\n        return this;\n    }\n\n    private void setMessageRoutingMode() throws PulsarClientException {\n        if (conf.getMessageRoutingMode() == null && conf.getCustomMessageRouter() == null) {\n            messageRoutingMode(MessageRoutingMode.RoundRobinPartition);\n        } else if (conf.getMessageRoutingMode() == null && conf.getCustomMessageRouter() != null) {\n            messageRoutingMode(MessageRoutingMode.CustomPartition);\n        } else if (conf.getMessageRoutingMode() == MessageRoutingMode.CustomPartition\n                && conf.getCustomMessageRouter() == null) {\n            throw new PulsarClientException(\"When 'messageRoutingMode' is \" + MessageRoutingMode.CustomPartition\n                + \", 'messageRouter' should be set\");\n        } else if (conf.getMessageRoutingMode() != MessageRoutingMode.CustomPartition\n                && conf.getCustomMessageRouter() != null) {\n            throw new PulsarClientException(\"When 'messageRouter' is set, 'messageRoutingMode' \"\n                    + \"should be set as \" + MessageRoutingMode.CustomPartition);\n        }\n    }\n\n    @Override\n    public String toString() {\n        return conf != null ? conf.toString() : \"\";\n    }\n}\n","sourceCodeStart":383,"sourceCodeEnd":411,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ProducerBuilderImpl.java#L383-L411","documentation":"Thrown by ProducerBuilderImpl.setMessageRoutingMode when a custom MessageRouter is configured but messageRoutingMode is not CustomPartition. The router only takes effect under CustomPartition, so any other combination (e.g. router set with RoundRobinPartition) is treated as a misconfiguration and producer creation is rejected.","triggerScenarios":"Calling ProducerBuilder.messageRouter(router) while messageRoutingMode is unset, null, or explicitly set to SinglePartition/RoundRobinPartition/UseSinglePartition before create()/createAsync().","commonSituations":"Setting a router for partitioned topics but forgetting to switch the mode; a shared builder/helper that always installs a router; config files that supply the router but leave routing mode at default.","solutions":["Call producerBuilder.messageRoutingMode(MessageRoutingMode.CustomPartition) when installing a custom router.","Or remove the messageRouter(...) call if default routing is intended."],"exampleFix":"// before\nProducer<byte[]> p = client.newProducer().topic(topic)\n    .messageRouter(new MyMessageRouter()).create();\n// after\nProducer<byte[]> p = client.newProducer().topic(topic)\n    .messageRoutingMode(MessageRoutingMode.CustomPartition)\n    .messageRouter(new MyMessageRouter()).create();","handlingStrategy":"validation","validationCode":"if (conf.getCustomMessageRouter() != null && conf.getMessageRoutingMode() != MessageRoutingMode.CustomPartition) {\n    throw new IllegalArgumentException(\"messageRouter set but messageRoutingMode is not CustomPartition\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    producer = builder.create();\n} catch (PulsarClientException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"messageRoutingMode\")) {\n        builder.messageRoutingMode(MessageRoutingMode.CustomPartition); // align mode with router\n        producer = builder.create();\n    } else throw e;\n}","preventionTips":["Whenever you call messageRouter(...), immediately set messageRoutingMode(CustomPartition) on the same builder.","Avoid builders that install a router unconditionally; make router installation opt-in.","Document the mode+router coupling in shared producer-factory code."],"tags":["pulsar","client-configuration","producer","routing"],"backgroundTag":"inconsistent-message-routing-config","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}