apache/pulsar · error · IllegalArgumentException

The load shedding strategy: ${loadBalancerLoadSheddingStrate

Error message

The load shedding strategy: ${loadBalancerLoadSheddingStrategy} can't work with the placement strategy: ${loadBalancerLoadPlacementStrategy}

What it means

ModularLoadManagerImpl.initialize instantiates the configured placement strategy; if that class also implements LoadSheddingStrategy, the same instance is used for both placement and shedding, which is only allowed when loadBalancerLoadSheddingStrategy and loadBalancerLoadPlacementStrategy name the same class. Otherwise initialize throws IllegalArgumentException at broker startup.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/impl/ModularLoadManagerImpl.java:273

        sheddingExcludedNamespaceSelectionStrategy = new RoundRobinBrokerSelector();
        policies = new SimpleResourceAllocationPolicies(pulsar);
        filterPipeline.add(new BrokerLoadManagerClassFilter());
        filterPipeline.add(new BrokerVersionFilter());

        LoadManagerShared.refreshBrokerToFailureDomainMap(pulsar, brokerToFailureDomainMap);
        // register listeners for domain changes
        pulsarResources.getClusterResources().getFailureDomainResources()
                .registerListener(__ -> {
                    executors.execute(
                            () -> LoadManagerShared.refreshBrokerToFailureDomainMap(pulsar, brokerToFailureDomainMap));
                });

        if (placementStrategy instanceof LoadSheddingStrategy) {
            // if the placement strategy is also a load shedding strategy
            // we need to check two strategies are the same
            if (!conf.getLoadBalancerLoadSheddingStrategy().equals(
                    conf.getLoadBalancerLoadPlacementStrategy())) {
                throw new IllegalArgumentException("The load shedding strategy: "
                        + conf.getLoadBalancerLoadSheddingStrategy()
                        + " can't work with the placement strategy: "
                        + conf.getLoadBalancerLoadPlacementStrategy());
            }
            // bind the load shedding strategy and the placement strategy
            loadSheddingStrategy = (LoadSheddingStrategy) placementStrategy;
        } else {
            loadSheddingStrategy = createLoadSheddingStrategy();
        }
    }

    public void handleDataNotification(Notification t) {
        if (t.getPath().startsWith(LoadManager.LOADBALANCE_BROKERS_ROOT)) {
            brokersData.listLocks(LoadManager.LOADBALANCE_BROKERS_ROOT)
                    .thenAccept(brokers -> {
                        reapDeadBrokerPreallocations(brokers);
                    });

View on GitHub (pinned to 820761864e)

Solutions

  1. Make both properties reference the same strategy class, e.g. set loadBalancerLoadSheddingStrategy and loadBalancerLoadPlacementStrategy to the same FQN.
  2. Or revert loadBalancerLoadPlacementStrategy to a pure placement strategy that does not implement LoadSheddingStrategy (e.g. the default).
  3. Remove the custom combined strategy and use the standard shedding/placement pair.
  4. Validate the two config values together in deployment tooling before rollout.

Example fix

# before
loadBalancerLoadPlacementStrategy=org.apache.pulsar.broker.loadbalance.impl.MinimizeMemoryPlacementStrategyThatAlsoSheds
loadBalancerLoadSheddingStrategy=org.apache.pulsar.broker.loadbalance.impl.ThresholdShedder
# after (same class for both, or a pure placement strategy)
loadBalancerLoadPlacementStrategy=org.apache.pulsar.broker.loadbalance.impl.MinimizeMemoryPlacementStrategyThatAlsoSheds
loadBalancerLoadSheddingStrategy=org.apache.pulsar.broker.loadbalance.impl.MinimizeMemoryPlacementStrategyThatAlsoSheds
Defensive patterns

Strategy: validation

Validate before calling

Class<?> placement = Class.forName(conf.getLoadBalancerLoadPlacementStrategy());
if (LoadSheddingStrategy.class.isAssignableFrom(placement)
    && !conf.getLoadBalancerLoadSheddingStrategy()
        .equals(conf.getLoadBalancerLoadPlacementStrategy())) {
    throw new IllegalArgumentException("Shedding and placement strategies must match when placement sheds");
}

Type guard

boolean isCombinedStrategy(String placementClass) {
    try { return LoadSheddingStrategy.class.isAssignableFrom(Class.forName(placementClass)); }
    catch (ClassNotFoundException e) { return false; }
}

Try / catch

try {
    new ModularLoadManagerImpl(pulsar, coordinator, checkOwnershipRequired);
} catch (IllegalArgumentException e) {
    log.error("Load manager config invalid: {}", e.getMessage());
    // fail startup clearly instead of masking the config mistake
}

Prevention

When it happens

Trigger: Broker starts with loadBalancerLoadPlacementStrategy set to a class that implements LoadSheddingStrategy while loadBalancerLoadSheddingStrategy names a different class (default placement is NOT a shedding strategy, so this needs deliberate config).

Common situations: Operators copy configs between clusters and change only one of the two properties; custom placement strategies that implement both interfaces; typos where one property got a shedding class and the other kept the default.

Related errors


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