{"record":{"id":"3bc70c2872c5a085","repo":"apache/pulsar","slug":"extension-name-does-not-provide-a-protocol-ha","errorCode":null,"errorMessage":"extension `${name}` does NOT provide a protocol handler implementation","messagePattern":"extension `(.+?)` does NOT provide a protocol handler implementation","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"pulsar-proxy/src/main/java/org/apache/pulsar/proxy/extensions/ProxyExtensionsUtils.java","lineNumber":134,"sourceCode":"\n    /**\n     * Load the extension according to the handler definition.\n     *\n     * @param metadata the extension definition.\n     * @return\n     */\n    static ProxyExtensionWithClassLoader load(ProxyExtensionMetadata metadata,\n                                              String narExtractionDirectory) throws IOException {\n        final File narFile = metadata.getArchivePath().toAbsolutePath().normalize().toFile();\n        NarClassLoader ncl = NarClassLoaderBuilder.builder()\n                .narFile(narFile)\n                .parentClassLoader(ProxyExtension.class.getClassLoader())\n                .extractionDirectory(narExtractionDirectory)\n                .build();\n\n        ProxyExtensionDefinition phDef = getProxyExtensionDefinition(ncl);\n        if (StringUtils.isBlank(phDef.getExtensionClass())) {\n            throw new IOException(\"extension `\" + phDef.getName() + \"` does NOT provide a protocol\"\n                + \" handler implementation\");\n        }\n\n        try {\n            Class<?> extensionClass = ncl.loadClass(phDef.getExtensionClass());\n            Object extension = extensionClass.getDeclaredConstructor().newInstance();\n            if (!(extension instanceof ProxyExtension)) {\n                throw new IOException(\"Class \" + phDef.getExtensionClass()\n                    + \" does not implement extension interface\");\n            }\n            ProxyExtension ph = (ProxyExtension) extension;\n            return new ProxyExtensionWithClassLoader(ph, ncl);\n        } catch (Throwable t) {\n            rethrowIOException(t);\n            return null;\n        }\n    }\n","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/extensions/ProxyExtensionsUtils.java#L116-L152","documentation":"Thrown by ProxyExtensionsUtils.load when the NAR's ProxyExtensionDefinition metadata omits the extensionClass field. The NAR unpacks fine, but it does not point to any class implementing the proxy extension interface, so there is nothing to instantiate.","triggerScenarios":"Loading an extension NAR whose META-INF/proxyextension.yaml (ProxyExtensionDefinition) has a blank extensionClass property — typically a hand-built or mispackaged NAR missing the required descriptor entry.","commonSituations":"Building a custom extension NAR without adding extensionClass to the descriptor; packaging an empty/placeholder NAR; a broken release artifact from a CI pipeline that skipped the metadata generation step.","solutions":["Add the extensionClass property to the NAR's proxy extension definition file, pointing at the class implementing ProxyExtension","Rebuild the extension NAR with the official Pulsar proxy-extension archetype/template so metadata is generated","Re-download the official release NAR if the artifact came from a repository and may be corrupt","Verify with 'unzip -p your.nar META-INF/proxyextension.yaml' that name and extensionClass are populated"],"exampleFix":"// before (META-INF/proxyextension.yaml)\nname: myext\n// after\nname: myext\nextensionClass: org.example.MyProxyExtension","handlingStrategy":"validation","validationCode":"// Verify the NAR descriptor before loading\nString yaml = readNarEntry(narFile, \"META-INF/proxyextension.yaml\");\nif (yaml == null || !yaml.contains(\"extensionClass:\"))\n    throw new IllegalStateException(\"NAR missing extensionClass in proxyextension.yaml\");","typeGuard":null,"tryCatchPattern":"try { proxyExtensions.load(conf); } catch (RuntimeException e) { if (e.getMessage().contains(\"does NOT provide\")) log.error(\"Rebuild NAR: extensionClass missing from descriptor\"); throw e; }","preventionTips":["Build custom NARs from the official Pulsar extension template","Inspect META-INF/proxyextension.yaml in CI before publishing the artifact"],"tags":["pulsar-proxy","extensions","nar-packaging"],"backgroundTag":"missing-extension-descriptor","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"}