apache/pulsar · error · IllegalArgumentException

Error when loading topic compaction strategy:

Error message

Error when loading topic compaction strategy: 

What it means

Thrown as an IllegalArgumentException by TopicCompactionStrategy.load when the configured strategy class cannot be instantiated — the class name fails Class.forName (not on classpath), has no no-arg constructor, the constructor fails, or the class is not assignable to TopicCompactionStrategy (ClassCastException inside the catch). The original exception is attached as the cause.

Solutions

  1. Verify the class name string matches the fully-qualified name exactly and check the cause exception for the root failure
  2. Deploy the jar containing the strategy on the broker's classpath (or use a built-in strategy)
  3. Ensure the class has a public no-arg constructor and extends TopicCompactionStrategy<T>
  4. Check the loaded jar's Pulsar version matches the broker to avoid linkage/instantiation errors

Example fix

// before
setCompactionStrategy("com.acme.CompactV2") // class not deployed / no no-arg ctor
// after
setCompactionStrategy("com.acme.compaction.CompactV2Strategy") // jar in lib/, public no-arg constructor, extends TopicCompactionStrategy<Msg>
Defensive patterns

Strategy: try-catch

Validate before calling

try {
    Class<?> c = Class.forName(className, true, getClass().getClassLoader());
    if (!TopicCompactionStrategy.class.isAssignableFrom(c)) throw new IllegalStateException("not a TopicCompactionStrategy");
    c.getDeclaredConstructor(); // requires public no-arg ctor
} catch (ClassNotFoundException | NoSuchMethodException e) {
    throw new IllegalArgumentException("strategy class unusable: " + className, e);
}

Type guard

static boolean isLoadableStrategy(String className, ClassLoader cl) {
    try {
        Class<?> c = Class.forName(className, false, cl);
        return TopicCompactionStrategy.class.isAssignableFrom(c);
    } catch (Throwable t) { return false; }
}

Try / catch

try {
    TopicCompactionStrategy.load(name, tag);
} catch (IllegalArgumentException e) {
    log.error("Bad compaction strategy {}: {}", name, e.getCause(), e);
    // fall back to a default strategy or fail the topic policy validation
}

Prevention

When it happens

Trigger: Calling load(topicCompactionStrategyClassName, tag) with a class name that is misspelled, not on the classpath, lacks a public no-arg constructor, throws in its constructor, or does not extend TopicCompactionStrategy (causing the cast to fail).

Common situations: Typo in the compactionStrategyClassName topic policy; custom strategy jar not deployed to broker; strategy class refactored/renamed or its no-arg constructor removed; loading a class from a different major version of Pulsar; packaging a class with the wrong generic type so the unchecked cast fails at runtime.

Related errors


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

Appendix: source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/topics/TopicCompactionStrategy.java:89

    default void handleSkippedMessage(String key, T cur) {
    }


    @SuppressWarnings("unchecked") // Instance created via reflection; caller is responsible for type safety
    static <T> TopicCompactionStrategy<T> load(String tag, String topicCompactionStrategyClassName) {
        if (topicCompactionStrategyClassName == null) {
            return null;
        }

        try {
            Class<?> clazz = Class.forName(topicCompactionStrategyClassName);
            TopicCompactionStrategy<T> instance =
                    (TopicCompactionStrategy<T>) clazz.getDeclaredConstructor().newInstance();
            INSTANCES.put(tag, instance);
            return instance;
        } catch (Exception e) {
            throw new IllegalArgumentException(
                    "Error when loading topic compaction strategy: " + topicCompactionStrategyClassName, e);
        }
    }

    @SuppressWarnings("unchecked") // Caller is responsible for type safety
    static <T> TopicCompactionStrategy<T> getInstance(String tag) {
        return (TopicCompactionStrategy<T>) INSTANCES.get(tag);
    }
}

View on GitHub (pinned to 820761864e)