{"record":{"id":"9983cfbf69c562e7","repo":"apache/pulsar","slug":"error-when-loading-topic-compaction-strategy","errorCode":null,"errorMessage":"Error when loading topic compaction strategy: ","messagePattern":"Error when loading topic compaction strategy: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-common/src/main/java/org/apache/pulsar/common/topics/TopicCompactionStrategy.java","lineNumber":89,"sourceCode":"\n    default void handleSkippedMessage(String key, T cur) {\n    }\n\n\n    @SuppressWarnings(\"unchecked\") // Instance created via reflection; caller is responsible for type safety\n    static <T> TopicCompactionStrategy<T> load(String tag, String topicCompactionStrategyClassName) {\n        if (topicCompactionStrategyClassName == null) {\n            return null;\n        }\n\n        try {\n            Class<?> clazz = Class.forName(topicCompactionStrategyClassName);\n            TopicCompactionStrategy<T> instance =\n                    (TopicCompactionStrategy<T>) clazz.getDeclaredConstructor().newInstance();\n            INSTANCES.put(tag, instance);\n            return instance;\n        } catch (Exception e) {\n            throw new IllegalArgumentException(\n                    \"Error when loading topic compaction strategy: \" + topicCompactionStrategyClassName, e);\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\") // Caller is responsible for type safety\n    static <T> TopicCompactionStrategy<T> getInstance(String tag) {\n        return (TopicCompactionStrategy<T>) INSTANCES.get(tag);\n    }\n}\n","sourceCodeStart":71,"sourceCodeEnd":99,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-common/src/main/java/org/apache/pulsar/common/topics/TopicCompactionStrategy.java#L71-L99","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Verify the class name string matches the fully-qualified name exactly and check the cause exception for the root failure","Deploy the jar containing the strategy on the broker's classpath (or use a built-in strategy)","Ensure the class has a public no-arg constructor and extends TopicCompactionStrategy<T>","Check the loaded jar's Pulsar version matches the broker to avoid linkage/instantiation errors"],"exampleFix":"// before\nsetCompactionStrategy(\"com.acme.CompactV2\") // class not deployed / no no-arg ctor\n// after\nsetCompactionStrategy(\"com.acme.compaction.CompactV2Strategy\") // jar in lib/, public no-arg constructor, extends TopicCompactionStrategy<Msg>","handlingStrategy":"try-catch","validationCode":"try {\n    Class<?> c = Class.forName(className, true, getClass().getClassLoader());\n    if (!TopicCompactionStrategy.class.isAssignableFrom(c)) throw new IllegalStateException(\"not a TopicCompactionStrategy\");\n    c.getDeclaredConstructor(); // requires public no-arg ctor\n} catch (ClassNotFoundException | NoSuchMethodException e) {\n    throw new IllegalArgumentException(\"strategy class unusable: \" + className, e);\n}","typeGuard":"static boolean isLoadableStrategy(String className, ClassLoader cl) {\n    try {\n        Class<?> c = Class.forName(className, false, cl);\n        return TopicCompactionStrategy.class.isAssignableFrom(c);\n    } catch (Throwable t) { return false; }\n}","tryCatchPattern":"try {\n    TopicCompactionStrategy.load(name, tag);\n} catch (IllegalArgumentException e) {\n    log.error(\"Bad compaction strategy {}: {}\", name, e.getCause(), e);\n    // fall back to a default strategy or fail the topic policy validation\n}","preventionTips":["Fully qualify the strategy class name and test it with Class.forName before configuring","Deploy the strategy jar to every broker's classpath","Keep a public no-arg constructor on strategy classes","Pin plugin jar versions to the broker's Pulsar version"],"tags":["reflection","classloading","configuration","compaction"],"backgroundTag":"class-not-found","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"}