{"record":{"id":"ead63184b32a92d1","repo":"apache/pulsar","slug":"configuredservice-should-not-be-an-instance-of-sys","errorCode":null,"errorMessage":"configuredService should not be an instance of SystemTopicBasedTopicPoliciesService","messagePattern":"configuredService should not be an instance of SystemTopicBasedTopicPoliciesService","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/service/LegacyAwareTopicPoliciesService.java","lineNumber":70,"sourceCode":"                                           SystemTopicBasedTopicPoliciesService systemTopicService,\n                                           TopicPoliciesService configuredService) {\n        // Generally, we only need to check if the __change_events topic exists once because the __change_events topic\n        // should only be created by broker before the upgrade, where `SystemTopicBasedTopicPoliciesService` is\n        // configured as the topic policies service.\n        this.isLegacyNamespace = Caffeine.newBuilder().expireAfterWrite(Duration.ofHours(1))\n                .buildAsync(new AsyncCacheLoader<>() {\n                    @NonNull\n                    @Override\n                    public CompletableFuture<? extends Boolean> asyncLoad(NamespaceName key,\n                                                                          @NonNull Executor executor) {\n                        return NamespaceEventsSystemTopicFactory.checkSystemTopicExists(key, EventType.TOPIC_POLICY,\n                                pulsar);\n                    }\n                });\n        this.systemTopicService = systemTopicService;\n        this.configuredService = configuredService;\n        if (configuredService instanceof SystemTopicBasedTopicPoliciesService) {\n            throw new IllegalArgumentException(\n                    \"configuredService should not be an instance of SystemTopicBasedTopicPoliciesService\");\n        }\n    }\n\n    @Override\n    public void start(PulsarService pulsarService) {\n        // We should not call `systemTopicService.start()`, which just registers a namespace bundle listener to create\n        // a reader on `<namespace>/__change_events` when the namespace's bundle is loaded firstly. It's just an\n        // optimization to create the reader before loading any topic. However, it could create a reader on a namespace\n        // that does not even have the __change_events topic.\n        configuredService.start(pulsarService);\n    }\n\n    @Override\n    public void close() throws Exception {\n        try {\n            configuredService.close();\n        } finally {","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/LegacyAwareTopicPoliciesService.java#L52-L88","documentation":"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.","triggerScenarios":"Programmatically constructing LegacyAwareTopicPoliciesService(pulsar, systemTopicService, configuredService) where configuredService instanceof SystemTopicBasedTopicPoliciesService.","commonSituations":"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.","solutions":["Pass the legacy/in-memory TopicPoliciesService (e.g. InMemoryTopicPoliciesService) as configuredService, not the system-topic one","Swap the constructor arguments if systemTopicService and configuredService were mixed up","Update broker extension code to the current TopicPoliciesService wiring API"],"exampleFix":"// before\nnew LegacyAwareTopicPoliciesService(pulsar, systemTopicService, systemTopicService);\n// after\nnew LegacyAwareTopicPoliciesService(pulsar, systemTopicService, new InMemoryTopicPoliciesService());","handlingStrategy":"type-guard","validationCode":"if (configuredService instanceof SystemTopicBasedTopicPoliciesService) {\n    throw new IllegalArgumentException(\"pass the legacy service as configuredService\");\n}","typeGuard":"boolean isValidConfiguredService(TopicPoliciesService s) {\n    return !(s instanceof SystemTopicBasedTopicPoliciesService);\n}","tryCatchPattern":"try {\n    new LegacyAwareTopicPoliciesService(pulsar, systemTopicService, configuredService);\n} catch (IllegalArgumentException e) {\n    log.error(\"Wrong TopicPoliciesService wiring\", e);\n}","preventionTips":["Follow current Pulsar broker startup wiring order for topic policy services","Add instanceof assertions in extension code before constructing","Re-check wiring code after Pulsar upgrades"],"tags":["java","broker","topic-policies","configuration","illegal-argument"],"backgroundTag":"invalid-service-wiring","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"}