apache/pulsar · error · UnsupportedOperationException

Use #choosePartition(Message, TopicMetadata) instead

Error message

Use #choosePartition(Message, TopicMetadata) instead

What it means

The single-argument MessageRouter.choosePartition(Message) default method is deprecated and its default implementation deliberately throws UnsupportedOperationException to force routers to migrate to choosePartition(Message, TopicMetadata). If a custom router does not override either method (or caller code invokes the old overload on a router that only inherits the default), this error is thrown at produce time.

Source

Thrown at pulsar-client-api/src/main/java/org/apache/pulsar/client/api/MessageRouter.java:45

 * to a producer to select the partition that a particular
 * messsage should be published on.
 *
 * @see ProducerBuilder#messageRouter(MessageRouter)
 */
@InterfaceAudience.Public
@InterfaceStability.Stable
public interface MessageRouter extends Serializable {

    /**
     *
     * @param msg
     *            Message object
     * @return The index of the partition to use for the message
     * @deprecated since 1.22.0. Please use {@link #choosePartition(Message, TopicMetadata)} instead.
     */
    @Deprecated
    default int choosePartition(Message<?> msg) {
        throw new UnsupportedOperationException("Use #choosePartition(Message, TopicMetadata) instead");
    }

    /**
     * Choose a partition based on msg and the topic metadata.
     *
     * @param msg message to route
     * @param metadata topic metadata
     * @return the partition to route the message.
     * @since 1.22.0
     */
    default int choosePartition(Message<?> msg, TopicMetadata metadata) {
        return choosePartition(msg);
    }

}

View on GitHub (pinned to 820761864e)

Solutions

  1. Implement choosePartition(Message<?>, TopicMetadata) in your custom router and use topicMetadata.numPartitions() instead of hardcoding the partition count.
  2. If you maintain a wrapper, forward the deprecated call: return choosePartition(msg, TopicMetadata.INVALID).
  3. Remove any direct call sites that invoke the one-argument overload; always route through the metadata-aware API.

Example fix

// before
class MyRouter implements MessageRouter {
    @Override
    public int choosePartition(Message<?> msg) { return hash(msg) % 3; }
}
// after
class MyRouter implements MessageRouter {
    @Override
    public int choosePartition(Message<?> msg, TopicMetadata metadata) {
        return hash(msg) % metadata.numPartitions();
    }
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Fail fast in tests: routers must implement the metadata-aware overload
static void checkRouter(MessageRouter router) {
    if (!Arrays.stream(router.getClass().getMethods())
            .anyMatch(m -> m.getName().equals("choosePartition")
                && m.getParameterCount() == 2))
        throw new IllegalStateException("Router must implement choosePartition(Message, TopicMetadata)");
}

Type guard

static boolean supportsMetadataRouting(MessageRouter router) {
    try {
        router.getClass().getMethod("choosePartition", Message.class, TopicMetadata.class);
        return true;
    } catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
    int partition = router.choosePartition(msg);
} catch (UnsupportedOperationException e) {
    // deprecated overload not implemented — migrate call site to choosePartition(msg, metadata)
}

Prevention

When it happens

Trigger: Implementing a custom MessageRouter that overrides nothing (or only the deprecated overload) and then calling router.choosePartition(msg) directly, or producing with a ClientBuilder-level router whose only override is the deprecated method on a code path that never delegates.

Common situations: Upgrading from pre-1.22 code where the single-arg method was the contract; tutorials copied from old blog posts; a router class left abstract over the new signature after the API migration.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/9c687c299c4cd7f7. Report an issue: GitHub.