apache/cassandra · critical · ConfigurationException

Invalid parameterized class <providerClass.getName()>: must…

Error message

Invalid parameterized class <providerClass.getName()>: must extend or implement <expectedType.getName()>

What it means

After resolving a configured class by name, ParameterizedClass.newInstance verifies (once, after package search) that the resolved class extends or implements the expected type. If it exists but has the wrong type (e.g. a class configured as an authenticator that doesn't implement IAuthenticator), ConfigurationException is thrown naming both the found class and required type.

Solutions

  1. Make the configured class implement/extend the expected type named in the message.
  2. Correct the config to reference the class intended for that slot.
  3. If the interface changed in an upgrade, update or recompile the custom class against the new API.

Example fix

// before
authenticator:
  class_name: com.example.MyAuthorizer  # wrong type
// after
authenticator:
  class_name: com.example.MyAuthenticator implements IAuthenticator
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName(fqcn, false, loader);
if (!expectedType.isAssignableFrom(c))
    throw new ConfigurationException(fqcn + " does not implement " + expectedType.getName());

Type guard

static boolean implementsExpected(String fqcn, Class<?> expected) throws ClassNotFoundException { return expected.isAssignableFrom(Class.forName(fqcn, false, ParameterizedClass.class.getClassLoader())); }

Try / catch

try { ParameterizedClass.newInstance(def, expectedType, packages); } catch (ConfigurationException e) { LOG.error("wrong type for slot {}: {}", def.class_name, e.getMessage()); throw e; }

Prevention

When it happens

Trigger: Pointing a config slot (authenticator, authorizer, seed provider, encryptor, etc.) at a class that exists on the classpath but implements the wrong interface, e.g. swapping authenticator and authorizer class names, or configuring a base/abstract or unrelated class.

Common situations: Copy-pasting the wrong FQCN between config slots; a custom class refactored to no longer implement the required interface; upgrading Cassandra where the interface contract changed; accidentally configuring an internal utility class.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/3e66438f4898cd87. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/config/ParameterizedClass.java:114

            }
            catch (ClassNotFoundException | NoClassDefFoundError e)
            {
                //no-op
            }
        }

        if (providerClass == null)
        {
            String pkgList = '[' + searchPackages.stream().map(p -> '"' + p + '"').collect(Collectors.joining(",")) + ']';
            String error = "Unable to find class " + parameterizedClass.class_name + " in packages " + pkgList;
            throw new ConfigurationException(error);
        }

        // Verify the resolved class is the expected extension type before it is initialized/instantiated. Done once,
        // after the package search, so a wrong-type match under an earlier search package does not abort the search
        // before a valid class under a later package is found.
        if (expectedType != null && !expectedType.isAssignableFrom(providerClass))
            throw new ConfigurationException("Invalid parameterized class " + providerClass.getName() +
                                             ": must extend or implement " + expectedType.getName());

        try
        {
            Constructor<?> mapConstructor = filterConstructor(providerClass, c -> c.getParameterTypes().length == 1 && c.getParameterTypes()[0].equals(Map.class));
            if (mapConstructor != null)
                return (K) mapConstructor.newInstance(parameterizedClass.parameters == null ? Collections.emptyMap() : parameterizedClass.parameters);

            // Falls-back to no-arg constructor
            Constructor<?> noArgsConstructor = filterConstructor(providerClass, c -> c.getParameterTypes().length == 0);
            if (noArgsConstructor != null)
                return (K) noArgsConstructor.newInstance();

            throw new ConfigurationException("No valid constructor found for class " + parameterizedClass.class_name);
        }
        catch (IllegalAccessException | InstantiationException | ExceptionInInitializerError e)
        {
            throw new ConfigurationException("Unable to instantiate parameterized class " + parameterizedClass.class_name, e);

View on GitHub (pinned to 88fd0f6a0e)