apache/pulsar · error · IllegalArgumentException

configuredService should not be an instance of SystemTopicBa

Error message

configuredService should not be an instance of SystemTopicBasedTopicPoliciesService

What it means

LegacyAwareTopicPoliciesService wraps a configured TopicPoliciesService and delegates to the system-topic service. Passing a SystemTopicBasedTopicPoliciesService as the configuredService is invalid (it would recursively wrap itself), so the constructor throws IllegalArgumentException.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/LegacyAwareTopicPoliciesService.java:70

                                           SystemTopicBasedTopicPoliciesService systemTopicService,
                                           TopicPoliciesService configuredService) {
        // Generally, we only need to check if the __change_events topic exists once because the __change_events topic
        // should only be created by broker before the upgrade, where `SystemTopicBasedTopicPoliciesService` is
        // configured as the topic policies service.
        this.isLegacyNamespace = Caffeine.newBuilder().expireAfterWrite(Duration.ofHours(1))
                .buildAsync(new AsyncCacheLoader<>() {
                    @NonNull
                    @Override
                    public CompletableFuture<? extends Boolean> asyncLoad(NamespaceName key,
                                                                          @NonNull Executor executor) {
                        return NamespaceEventsSystemTopicFactory.checkSystemTopicExists(key, EventType.TOPIC_POLICY,
                                pulsar);
                    }
                });
        this.systemTopicService = systemTopicService;
        this.configuredService = configuredService;
        if (configuredService instanceof SystemTopicBasedTopicPoliciesService) {
            throw new IllegalArgumentException(
                    "configuredService should not be an instance of SystemTopicBasedTopicPoliciesService");
        }
    }

    @Override
    public void start(PulsarService pulsarService) {
        // We should not call `systemTopicService.start()`, which just registers a namespace bundle listener to create
        // a reader on `<namespace>/__change_events` when the namespace's bundle is loaded firstly. It's just an
        // optimization to create the reader before loading any topic. However, it could create a reader on a namespace
        // that does not even have the __change_events topic.
        configuredService.start(pulsarService);
    }

    @Override
    public void close() throws Exception {
        try {
            configuredService.close();
        } finally {

View on GitHub (pinned to 820761864e)

Solutions

  1. Pass the legacy/in-memory TopicPoliciesService (e.g. InMemoryTopicPoliciesService) as configuredService, not the system-topic one
  2. Swap the constructor arguments if systemTopicService and configuredService were mixed up
  3. Update broker extension code to the current TopicPoliciesService wiring API

Example fix

// before
new LegacyAwareTopicPoliciesService(pulsar, systemTopicService, systemTopicService);
// after
new LegacyAwareTopicPoliciesService(pulsar, systemTopicService, new InMemoryTopicPoliciesService());
Defensive patterns

Strategy: type-guard

Validate before calling

if (configuredService instanceof SystemTopicBasedTopicPoliciesService) {
    throw new IllegalArgumentException("pass the legacy service as configuredService");
}

Type guard

boolean isValidConfiguredService(TopicPoliciesService s) {
    return !(s instanceof SystemTopicBasedTopicPoliciesService);
}

Try / catch

try {
    new LegacyAwareTopicPoliciesService(pulsar, systemTopicService, configuredService);
} catch (IllegalArgumentException e) {
    log.error("Wrong TopicPoliciesService wiring", e);
}

Prevention

When it happens

Trigger: Programmatically constructing LegacyAwareTopicPoliciesService(pulsar, systemTopicService, configuredService) where configuredService instanceof SystemTopicBasedTopicPoliciesService.

Common situations: Custom broker extension code wiring topic policy services in the wrong order (passing the system-topic service as the legacy/base service); misreading constructor parameter order; plugin configuration code written for an older Pulsar version.

Related errors


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