{"record":{"id":"0ef21c43800f7ea6","repo":"apache/pulsar","slug":"failed-to-initialize-authorization-manager-due-to","errorCode":null,"errorMessage":"Failed to initialize authorization manager due to empty ConfigurationStoreServers","messagePattern":"Failed to initialize authorization manager due to empty ConfigurationStoreServers","errorType":"exception","errorClass":"PulsarServerException","httpStatus":null,"severity":"critical","filePath":"pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketService.java","lineNumber":115,"sourceCode":"    }\n\n    public void start() throws PulsarServerException, PulsarClientException, MalformedURLException, ServletException {\n\n        if (isNotBlank(config.getConfigurationMetadataStoreUrl())) {\n            try {\n                configMetadataStore = createConfigMetadataStore(config.getConfigurationMetadataStoreUrl(),\n                        (int) config.getMetadataStoreSessionTimeoutMillis(),\n                        config.isMetadataStoreAllowReadOnlyOperations());\n            } catch (MetadataStoreException e) {\n                throw new PulsarServerException(e);\n            }\n            pulsarResources = new PulsarResources(null, configMetadataStore);\n        }\n\n        // start authorizationService\n        if (config.isAuthorizationEnabled()) {\n            if (pulsarResources == null) {\n                throw new PulsarServerException(\n                        \"Failed to initialize authorization manager due to empty ConfigurationStoreServers\");\n            }\n            authorizationService = new AuthorizationService(this.config, pulsarResources);\n        }\n        // start authentication service\n        authenticationService = new AuthenticationService(this.config);\n        // initialize crypto key reader\n        String cryptoFactoryClassName = (String) config.getProperties().get(\"cryptoKeyReaderFactoryClassName\");\n        if (StringUtils.isNotBlank(cryptoFactoryClassName)) {\n            try {\n                CryptoKeyReaderFactory factoryInstance = (CryptoKeyReaderFactory) Class.forName(cryptoFactoryClassName)\n                        .getDeclaredConstructor().newInstance();\n                cryptoKeyReader = Optional.ofNullable(factoryInstance.create());\n            } catch (Exception e) {\n                log.info().exception(e).log(\"Failed to initialize crypto-key reader\");\n                throw new PulsarServerException(e);\n            }\n        }","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketService.java#L97-L133","documentation":"WebSocketService.start() enables the authorizationService when config.isAuthorizationEnabled() is true, but authorization needs cluster/config metadata resources built from ConfigurationStoreServers. If pulsarResources was never created (ConfigurationStoreServers empty/null) it throws PulsarServerException, aborting service startup.","triggerScenarios":"WebSocket proxy config has authorizationEnabled=true while configurationStoreServers is unset or empty, so the PulsarResources initialization branch (which requires a config metadata store URL) is skipped.","commonSituations":"Standalone websocket proxy deployed with auth enabled but no configuration store URL in websocket.conf; copying a broker config without the configurationStoreServers key; enabling authorization in dev without pointing the proxy at the cluster's metadata store.","solutions":["Set configurationStoreServers in the websocket proxy configuration to the cluster's config metadata store URL","If the proxy does not need authorization, set authorizationEnabled=false","Verify the configuration actually loads the value (check the effective config, not just the file) and restart the service","Ensure the metadata store URL is reachable once set, or the next startup stage will fail"],"exampleFix":"// before\nauthorizationEnabled=true\n# configurationStoreServers unset\n// after\nauthorizationEnabled=true\nconfigurationStoreServers=zk1:2181","handlingStrategy":"validation","validationCode":"if (conf.isAuthorizationEnabled() && (conf.getConfigurationStoreServers() == null || conf.getConfigurationStoreServers().isBlank())) { throw new IllegalStateException(\"configurationStoreServers must be set when authorizationEnabled=true\"); }","typeGuard":"boolean authConfigValid(WebSocketProxyConfiguration c) { return !c.isAuthorizationEnabled() || (c.getConfigurationStoreServers() != null && !c.getConfigurationStoreServers().isEmpty()); }","tryCatchPattern":"try { service.start(); } catch (PulsarServerException e) { if (e.getMessage().contains(\"ConfigurationStoreServers\")) { failFast(\"Set configurationStoreServers or disable authorization\"); } throw e; }","preventionTips":["Fail fast on startup by validating auth config before start()","Keep websocket proxy config in sync with broker config for auth keys","Document configurationStoreServers as a prerequisite for authorizationEnabled","Smoke-test startup in CI with production-like config"],"tags":["configuration","authorization","startup"],"backgroundTag":"missing-config-property","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}