{"record":{"id":"c258bee219eeac20","repo":"apache/pulsar","slug":"class-entryfilterclass-does-not-implement-entry","errorCode":null,"errorMessage":"Class ${entryFilterClass} does not implement entry filter interface","messagePattern":"Class (.+?) does not implement entry filter interface","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/service/plugin/EntryFilterProvider.java","lineNumber":203,"sourceCode":"\n    @SuppressWarnings(\"unchecked\")\n    protected EntryFilter load(EntryFilterMetaData metadata)\n            throws IOException {\n        final EntryFilterDefinition def = metadata.getDefinition();\n        if (StringUtils.isBlank(def.getEntryFilterClass())) {\n            throw new RuntimeException(\"Entry filter `\" + def.getName() + \"` does NOT provide a entry\"\n                    + \" filters implementation\");\n        }\n        try {\n            final NarClassLoader ncl = getNarClassLoader(metadata.getArchivePath());\n            if (ncl == null) {\n                throw new RuntimeException(\"Entry filter `\" + def.getName() + \"` cannot be loaded, \"\n                        + \"see the broker logs for further details\");\n            }\n            Class entryFilterClass = ncl.loadClass(def.getEntryFilterClass());\n            Object filter = entryFilterClass.getDeclaredConstructor().newInstance();\n            if (!(filter instanceof EntryFilter)) {\n                throw new IOException(\"Class \" + def.getEntryFilterClass()\n                        + \" does not implement entry filter interface\");\n            }\n            EntryFilter pi = (EntryFilter) filter;\n            // the classloader is shared with the broker, the instance doesn't own it\n            return new EntryFilterWithClassLoader(pi, ncl, false);\n        } catch (Throwable e) {\n            if (e instanceof IOException) {\n                throw (IOException) e;\n            }\n            log.error()\n                    .attr(\"entryFilterClass\", metadata.getDefinition().getEntryFilterClass())\n                    .exception(e)\n                    .log(\"Failed to load class\");\n            throw new IOException(e);\n        }\n    }\n\n    private NarClassLoader getNarClassLoader(Path archivePath) {","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/plugin/EntryFilterProvider.java#L185-L221","documentation":"load() instantiates the configured class via reflection and verifies it implements the EntryFilter interface before wrapping it in EntryFilterWithClassLoader. If the class instantiates but is not an EntryFilter, an IOException is thrown naming the offending class.","triggerScenarios":"entryFilterClass in the filter definition points to a valid class that does not implement org.apache.pulsar.broker.service.plugin.EntryFilter (wrong class name, wrong version of the class, or a helper class referenced by mistake).","commonSituations":"Definition written against an old interface/package that changed between Pulsar versions; copy-pasted class name from another plugin type (e.g. a BrokerEntryMetadataFilter); class compiled against a different EntryFilter interface so instanceof fails.","solutions":["Set entryFilterClass to a class that directly implements EntryFilter and rebuild the NAR","Verify the interface package/name matches the broker's EntryFilter version","Compile the filter against the same Pulsar version as the running broker"],"exampleFix":"// before\npublic class AuditEntryFilter { /* no interface */ }\n// after\npublic class AuditEntryFilter implements org.apache.pulsar.broker.service.plugin.EntryFilter { ... }","handlingStrategy":"validation","validationCode":"Class<?> c = ncl.loadClass(def.getEntryFilterClass());\nif (!org.apache.pulsar.broker.service.plugin.EntryFilter.class.isAssignableFrom(c)) {\n    throw new IllegalStateException(def.getEntryFilterClass() + \" does not implement EntryFilter\");\n}","typeGuard":"boolean isEntryFilterClass(String className, NarClassLoader ncl) {\n    try { return EntryFilter.class.isAssignableFrom(ncl.loadClass(className)); }\n    catch (ClassNotFoundException e) { return false; }\n}","tryCatchPattern":"try {\n    EntryFilter f = provider.load(metadata);\n} catch (IOException e) {\n    log.error(\"{} does not implement EntryFilter; fix the definition or the class\", e.getMessage());\n}","preventionTips":["Compile filter NARs against the broker's Pulsar version","Add a unit test asserting the configured class implements EntryFilter","Never point entryFilterClass at helper/abstract classes"],"tags":["pulsar","entry-filter","nar-loading","type-mismatch"],"backgroundTag":"plugin-class-not-implementing-interface","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"}