apache/dubbo · error · IllegalArgumentException
Extension type == null
Error message
Extension type == null
What it means
Thrown by ExtensionDirector.getExtensionLoader(Class<T> type) when the type argument is null. Dubbo's SPI system requires a non-null interface class to resolve the corresponding ExtensionLoader. This is the first guard in the extension resolution pipeline — a null type means no meaningful lookup is possible.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirector.java:70
this.extensionPostProcessors.add(processor);
}
}
public List<ExtensionPostProcessor> getExtensionPostProcessors() {
return extensionPostProcessors;
}
@Override
public ExtensionDirector getExtensionDirector() {
return this;
}
@Override
@SuppressWarnings("unchecked")
public <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
checkDestroyed();
if (type == null) {
throw new IllegalArgumentException("Extension type == null");
}
if (!type.isInterface()) {
throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
}
if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type (" + type
+ ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
}
// 1. find in local cache
ExtensionLoader<T> loader = (ExtensionLoader<T>) extensionLoadersMap.get(type);
ExtensionScope scope = extensionScopeMap.get(type);
if (scope == null) {
SPI annotation = type.getAnnotation(SPI.class);
scope = annotation.scope();
extensionScopeMap.put(type, scope);
}View on GitHub (pinned to 3a3043227f)
Solutions
- Inspect the stack trace to find which code path passes null to getExtensionLoader and trace the source of the Class<T> argument.
- Ensure the class reference is loaded via the correct ClassLoader and is not null before calling getExtensionLoader.
- Check that the relevant Dubbo module dependency (e.g., dubbo-rpc-api, dubbo-registry-api) is on the classpath so that the interface class constant resolves.
- If using shade/relocate, verify the relocation rules cover the package of the SPI interface.
Example fix
// before
ExtensionLoader<MySpi> loader = director.getExtensionLoader(spiClass); // spiClass is null
// after
if (spiClass == null) {
throw new IllegalStateException("MySpi class not loaded — check dubbo-rpc-api dependency");
}
ExtensionLoader<MySpi> loader = director.getExtensionLoader(spiClass); Defensive patterns
Strategy: validation
Validate before calling
if (type == null) {
throw new IllegalArgumentException("SPI type must not be null — check classpath and ClassLoader");
}
ExtensionLoader<T> loader = director.getExtensionLoader(type); Type guard
static <T> boolean isValidSpiType(Class<T> type) {
return type != null && type.isInterface() && type.isAnnotationPresent(SPI.class);
} Try / catch
try {
ExtensionLoader<T> loader = director.getExtensionLoader(type);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Extension type == null")) {
log.error("SPI type was null — likely a missing dependency or ClassLoader issue", e);
}
throw e;
} Prevention
- Always resolve SPI interface class constants through the same ClassLoader that loaded Dubbo.
- Use @SPI-annotated interface class constants directly (e.g., Protocol.class) rather than dynamic Class.forName without null checks.
- In test code, verify classpath includes the Dubbo module providing the SPI interface.
When it happens
Trigger: Calling extensionDirector.getExtensionLoader(null) directly, or more commonly passing a class reference that was resolved to null at runtime (e.g., a Class.forName() that failed silently, a static field that was not initialized, or a class that was shaded/relocated away during a dependency upgrade).
Common situations: Maven shade plugin relocated a package but code still references the old class constant which resolved to null. A custom ScopeModel or ExtensionDirector subclass forgot to pass the type. A plugin/module integration passes a class loaded from a different ClassLoader that returned null. After a Dubbo version upgrade where an SPI interface was renamed or moved.
Related errors
- Extension type (${type}) is not an interface!
- Extension type (${type}) is not an extension, because it is
- Extension name == null
- Not find extension: ${name}
- Input type ${clazz} doesn't implement the Extension ${type}
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/28d3a4a2bf968fe0.
Report an issue: GitHub.