apache/pulsar · error · IOException

extension `${name}` does NOT provide a protocol handler impl

Error message

extension `${name}` does NOT provide a protocol handler implementation

What it means

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.

Source

Thrown at pulsar-proxy/src/main/java/org/apache/pulsar/proxy/extensions/ProxyExtensionsUtils.java:134

    /**
     * Load the extension according to the handler definition.
     *
     * @param metadata the extension definition.
     * @return
     */
    static ProxyExtensionWithClassLoader load(ProxyExtensionMetadata metadata,
                                              String narExtractionDirectory) throws IOException {
        final File narFile = metadata.getArchivePath().toAbsolutePath().normalize().toFile();
        NarClassLoader ncl = NarClassLoaderBuilder.builder()
                .narFile(narFile)
                .parentClassLoader(ProxyExtension.class.getClassLoader())
                .extractionDirectory(narExtractionDirectory)
                .build();

        ProxyExtensionDefinition phDef = getProxyExtensionDefinition(ncl);
        if (StringUtils.isBlank(phDef.getExtensionClass())) {
            throw new IOException("extension `" + phDef.getName() + "` does NOT provide a protocol"
                + " handler implementation");
        }

        try {
            Class<?> extensionClass = ncl.loadClass(phDef.getExtensionClass());
            Object extension = extensionClass.getDeclaredConstructor().newInstance();
            if (!(extension instanceof ProxyExtension)) {
                throw new IOException("Class " + phDef.getExtensionClass()
                    + " does not implement extension interface");
            }
            ProxyExtension ph = (ProxyExtension) extension;
            return new ProxyExtensionWithClassLoader(ph, ncl);
        } catch (Throwable t) {
            rethrowIOException(t);
            return null;
        }
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Add the extensionClass property to the NAR's proxy extension definition file, pointing at the class implementing ProxyExtension
  2. Rebuild the extension NAR with the official Pulsar proxy-extension archetype/template so metadata is generated
  3. Re-download the official release NAR if the artifact came from a repository and may be corrupt
  4. Verify with 'unzip -p your.nar META-INF/proxyextension.yaml' that name and extensionClass are populated

Example fix

// before (META-INF/proxyextension.yaml)
name: myext
// after
name: myext
extensionClass: org.example.MyProxyExtension
Defensive patterns

Strategy: validation

Validate before calling

// Verify the NAR descriptor before loading
String yaml = readNarEntry(narFile, "META-INF/proxyextension.yaml");
if (yaml == null || !yaml.contains("extensionClass:"))
    throw new IllegalStateException("NAR missing extensionClass in proxyextension.yaml");

Try / catch

try { proxyExtensions.load(conf); } catch (RuntimeException e) { if (e.getMessage().contains("does NOT provide")) log.error("Rebuild NAR: extensionClass missing from descriptor"); throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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