{"record":{"id":"638be91b645534d9","repo":"apache/cassandra","slug":"invalid-s-class-s-must-extend-or-implement-s","errorCode":null,"errorMessage":"Invalid %s class '%s': must extend or implement %s","messagePattern":"Invalid (.+?) class '(.+?)': must extend or implement (.+?)","errorType":"exception","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/utils/FBUtilities.java","lineNumber":819,"sourceCode":"     * Loads a class without initializing it, then verifies it extends or implements the expected base type.\n     *\n     * @return The Class for the given name.\n     * @param classname Fully qualified classname.\n     * @param readable Descriptive noun for the role the class plays.\n     * @param expectedType Required superclass or interface.\n     * @param classLoader ClassLoader to use.\n     * @throws ConfigurationException If the class cannot be found or is not assignable to {@code expectedType}.\n     */\n    public static <T> Class<? extends T> classForNameWithoutInitialization(String classname,\n                                                                           String readable,\n                                                                           Class<T> expectedType,\n                                                                           ClassLoader classLoader) throws ConfigurationException\n    {\n        try\n        {\n            Class<?> klass = Class.forName(classname, false, classLoader);\n            if (!expectedType.isAssignableFrom(klass))\n                throw new ConfigurationException(String.format(\"Invalid %s class '%s': must extend or implement %s\",\n                                                               readable,\n                                                               classname,\n                                                               expectedType.getName()));\n            return klass.asSubclass(expectedType);\n        }\n        catch (ClassNotFoundException | NoClassDefFoundError e)\n        {\n            throw new ConfigurationException(String.format(\"Unable to find %s class '%s'\", readable, classname), e);\n        }\n    }\n\n    /**\n     * Constructs an instance of the given class, which must have a no-arg or default constructor.\n     * @param classname Fully qualified classname.\n     * @param readable Descriptive noun for the role the class plays.\n     * @throws ConfigurationException If the class cannot be found.\n     */\n    public static <T> T instanceOrConstruct(String classname, String readable) throws ConfigurationException","sourceCodeStart":801,"sourceCodeEnd":837,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/utils/FBUtilities.java#L801-L837","documentation":"classForNameWithoutInitialization loads a class without running its static initializers and verifies it extends/implements the expected base type. If the loaded class is not assignable to expectedType, a ConfigurationException reports the type mismatch with the required interface name. This guards pluggable configuration points against wrong types.","triggerScenarios":"Configuring a class name for a pluggable component (e.g. SSL factory, crypto provider, commit log archiver) that exists but implements the wrong interface — classForNameWithoutInitialization(name, readable, expectedType, ...) hits the isAssignableFrom check.","commonSituations":"Implementing the wrong interface in custom code; pointing a factory option at a class of a different plugin kind; copy-pasting a class name between config sections (e.g. audit logger name used as ssl_factory); refactor moved functionality to a new interface.","solutions":["Point the config at a class that actually implements/extends the required type (named in the message)","Fix your custom class to implement the expected interface","Check for similarly-named classes from different plugin families and pick the right one","Recompile/deploy the updated custom jar on all nodes"],"exampleFix":"// before\nssl_factory: com.example.MyAuditLogger  // wrong type\n// after\nssl_factory: com.example.MySslContextFactory implements org.apache.cassandra.security.ISslContextFactory","handlingStrategy":"validation","validationCode":"boolean isAssignable(String cn, Class<?> expected) {\n    try { return expected.isAssignableFrom(Class.forName(cn, false, Thread.currentThread().getContextClassLoader())); }\n    catch (Throwable t) { return false; }\n}\n// before config load: if (!isAssignable(sslFactoryName, ISslContextFactory.class)) failFast();","typeGuard":"boolean implementsPlugin(String cn, Class<?> expected) {\n    try { return expected.isAssignableFrom(Class.forName(cn, false, Thread.currentThread().getContextClassLoader())); }\n    catch (Throwable t) { return false; }\n}","tryCatchPattern":"try {\n    config.load();\n} catch (ConfigurationException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"must extend or implement\"))\n        logger.error(\"Configured class has the wrong type — fix class name in config\", e);\n    throw e;\n}","preventionTips":["Cross-check the config value against the interface documented for that config key","Avoid copy-pasting class names between different plugin config sections","Write unit tests that load configured plugin classes via the same code path","Implement the exact interface required, not a similarly-named one"],"tags":["type-mismatch","reflection","config"],"backgroundTag":"config-type-mismatch","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}