apache/pulsar · error · java.lang.RuntimeException

Entry filter `${name}` does NOT provide a entry filters impl

Error message

Entry filter `${name}` does NOT provide a entry filters implementation

What it means

EntryFilterProvider.load turns filter metadata into a live EntryFilter instance via a NAR classloader. The filter's EntryFilterDefinition must declare entryFilterClass; if it is blank the definition is malformed and the provider cannot know which class to instantiate, so it throws.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/plugin/EntryFilterProvider.java:191

        String configStr;

        try {
            configStr = ncl.getServiceDefinition(ENTRY_FILTER_DEFINITION_FILE + ".yaml");
        } catch (NoSuchFileException e) {
            configStr = ncl.getServiceDefinition(ENTRY_FILTER_DEFINITION_FILE + ".yml");
        }

        return ObjectMapperFactory.getYamlMapper().reader().readValue(
                configStr, EntryFilterDefinition.class
        );
    }

    @SuppressWarnings("unchecked")
    protected EntryFilter load(EntryFilterMetaData metadata)
            throws IOException {
        final EntryFilterDefinition def = metadata.getDefinition();
        if (StringUtils.isBlank(def.getEntryFilterClass())) {
            throw new RuntimeException("Entry filter `" + def.getName() + "` does NOT provide a entry"
                    + " filters implementation");
        }
        try {
            final NarClassLoader ncl = getNarClassLoader(metadata.getArchivePath());
            if (ncl == null) {
                throw new RuntimeException("Entry filter `" + def.getName() + "` cannot be loaded, "
                        + "see the broker logs for further details");
            }
            Class entryFilterClass = ncl.loadClass(def.getEntryFilterClass());
            Object filter = entryFilterClass.getDeclaredConstructor().newInstance();
            if (!(filter instanceof EntryFilter)) {
                throw new IOException("Class " + def.getEntryFilterClass()
                        + " does not implement entry filter interface");
            }
            EntryFilter pi = (EntryFilter) filter;
            // the classloader is shared with the broker, the instance doesn't own it
            return new EntryFilterWithClassLoader(pi, ncl, false);
        } catch (Throwable e) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Add the fully-qualified implementation class to entryFilterClass in the filter definition inside the NAR
  2. Rebuild and redeploy the filter NAR
  3. Verify the packaged definition file with: unzip -p filter.nar META-INF/.../entry_filter.yml

Example fix

// before (entry_filter.yml)
name: audit-filter
// after
name: audit-filter
entryFilterClass: com.example.filters.AuditEntryFilter
Defensive patterns

Strategy: validation

Validate before calling

EntryFilterDefinition def = metaData.getDefinition();
if (def == null || StringUtils.isBlank(def.getEntryFilterClass())) {
    throw new IllegalStateException("Filter NAR definition is missing entryFilterClass");
}

Type guard

boolean hasImplementationClass(EntryFilterMetaData md) {
    return md != null && md.getDefinition() != null && StringUtils.isNotBlank(md.getDefinition().getEntryFilterClass());
}

Try / catch

try {
    EntryFilter f = provider.load(metadata);
} catch (RuntimeException e) {
    log.error("Filter {} lacks implementation class in its definition", metadata.getName(), e);
}

Prevention

When it happens

Trigger: load() is called for a filter whose NAR's entry_filter.yml (or equivalent definition) omits or leaves empty the entryFilterClass field.

Common situations: Hand-written or templated filter definition file missing the class key; NAR build script packaged a default/empty definition; YAML key renamed or typo'd so it deserializes to null.

Related errors


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