apache/dubbo · error · IllegalStateException
Exception occurred when loading extension class (interface:
Error message
Exception occurred when loading extension class (interface: {}) What it means
Thrown by getExtensionClasses() when loadExtensionClasses() raises InterruptedException while scanning and parsing META-INF/dubbo/, META-INF/services/, and META-INF/dubbo/internal/ SPI resource files. The class loading of the SPI registry is interruptible, and if the thread is interrupted (interrupt status set) during the scan, this error wraps the InterruptedException and is re-thrown as IllegalStateException. It is also logged via COMMON_ERROR_LOAD_EXTENSION.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java:971
}
private Map<String, Class<?>> getExtensionClasses() {
Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) {
loadExtensionClassesLock.lock();
try {
classes = cachedClasses.get();
if (classes == null) {
try {
classes = loadExtensionClasses();
} catch (InterruptedException e) {
logger.error(
COMMON_ERROR_LOAD_EXTENSION,
"",
"",
"Exception occurred when loading extension class (interface: " + type + ")",
e);
throw new IllegalStateException(
"Exception occurred when loading extension class (interface: " + type + ")", e);
}
cachedClasses.set(classes);
}
} finally {
loadExtensionClassesLock.unlock();
}
}
return classes;
}
/**
* synchronized in getExtensionClasses
*/
@SuppressWarnings("deprecation")
private Map<String, Class<?>> loadExtensionClasses() throws InterruptedException {
checkDestroyed();
cacheDefaultExtensionName();View on GitHub (pinned to 3a3043227f)
Solutions
- Ensure SPI extensions are loaded eagerly at startup (call getSupportedExtensions() during boot) before the application reaches a state where threads may be interrupted.
- If the thread was legitimately interrupted, restore the interrupt status in your catch block (Thread.currentThread().interrupt()) and let the caller decide whether to retry.
- Avoid calling getExtension/getAdaptiveExtension from threads that may be interrupted mid-flight (shutdown hooks, cancelled tasks).
Example fix
// before: lazy load races with shutdown interrupt
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
loader.getExtension("x"); // may throw [144] if interrupt overlaps
}));
// after: pre-load at startup, restore interrupt in handler
loader.getSupportedExtensions(); // warm the cache early
try {
loader.getExtension("x");
} catch (IllegalStateException e) {
if (Thread.interrupted()) { /* shutdown race; expected */ }
} Defensive patterns
Strategy: try-catch
Validate before calling
// Warm the SPI cache early in the lifecycle before interrupts are possible extensionDirector.getExtensionLoader(MySpi.class).getSupportedExtensions();
Try / catch
try {
loader.getExtension(name);
} catch (IllegalStateException e) {
if (e.getCause() instanceof InterruptedException) {
Thread.currentThread().interrupt(); // restore status
log.warn("SPI load interrupted; will retry on next access");
} else throw e;
} Prevention
- Eagerly initialize SPI extensions during application bootstrap, not lazily during request handling.
- Avoid calling getExtension from shutdown hooks or interruptible worker threads.
- Restore interrupt status if you catch an InterruptedException-derived error.
When it happens
Trigger: The thread performing the first lazy load of extension classes (inside the loadExtensionClassesLock) receives Thread.interrupt() during the resource enumeration or URL stream reading of SPI config files. This typically happens in app shutdown hooks, thread-pool reclamation, or frameworks that interrupt worker threads.
Common situations: Application shutdown races with lazy SPI initialization; a thread pool that interrupts idle threads while Dubbo is still warming up; running inside a container/scheduler that sets interrupt status; very slow classpath/IO making the SPI scan overlap with an interrupt-driven lifecycle event.
Related errors
- ExtensionDirector is destroyed
- Extension instance (name: {}, class: {}) couldn't be instant
- Extension type == null
- More than 1 default extension name on extension {}: {}
- Error occurred when loading extension class (interface: {},
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/1c7d0cecab2c6602.
Report an issue: GitHub.