alibaba/canal · error · IllegalStateException
Extension instance(name: ${name}, class: ${type}) could not
Error message
Extension instance(name: ${name}, class: ${type}) could not be instantiated: class could not be found What it means
Thrown by the private 4-arg createExtension(name, key, spiDir, standbyDir) — the keyed-instance creation path — when the requested name is absent from the loaded extension class map. Same meaning as 209 but for per-key extension instances (extension name + key yields a dedicated instance stored under EXTENSION_KEY_INSTANCE).
Source
Thrown at connector/core/src/main/java/com/alibaba/otter/canal/connector/core/spi/ExtensionLoader.java:189
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
+ ") could not be instantiated: " + t.getMessage(), t);
}
}
@SuppressWarnings("unchecked")
private T createExtension(String name, String key, String spiDir, String standbyDir) {
Class<?> clazz = getExtensionClasses(spiDir, standbyDir).get(name);
if (clazz == null) {
throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
+ ") could not be instantiated: class could not be found");
}
try {
T instance = (T) EXTENSION_KEY_INSTANCE.get(name + "-" + key);
if (instance == null) {
EXTENSION_KEY_INSTANCE.putIfAbsent(name + "-" + key, clazz.newInstance());
instance = (T) EXTENSION_KEY_INSTANCE.get(name + "-" + key);
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
+ ") could not be instantiated: " + t.getMessage(), t);
}
}
private Map<String, Class<?>> getExtensionClasses(String spiDir, String standbyDir) {
Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) {View on GitHub (pinned to 87be50e876)
Solutions
- Verify the extension name is registered in META-INF/canal/<interface> and the jar is present.
- Check load-time logs/exceptions map for rejected entries (subtype/duplicate) that caused the name to be missing.
- Correct the name property driving the keyed lookup.
Example fix
// before
loader.getExtension("rabitmq", dest, spiDir, standbyDir); // typo
// after
loader.getExtension("rabbitmq", dest, spiDir, standbyDir); Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check name registration for keyed lookup
if (!isRegistered(interfaceType, name)) {
throw new IllegalStateException(
"keyed extension '" + name + "' not registered; verify plugin jar + descriptor");
}
loader.getExtension(name, key, spiDir, standbyDir); Try / catch
try {
return loader.getExtension(name, key, spiDir, standbyDir);
} catch (IllegalStateException e) {
if (e.getMessage().contains("could not be found")) {
throw new IllegalStateException(
"keyed extension '" + name + "' for key '" + key + "' missing", e);
}
throw e;
} Prevention
- Keep per-key extension descriptors consistent with single-key ones.
- Check load-time logs for rejected entries that drop the name.
When it happens
Trigger: Keyed getExtension(name, key,...) where name has no SPI entry; the implementation jar is missing; the entry was rejected at load time (stored in exceptions map, surfacing later as 'could not be found').
Common situations: Per-destination producer loading where the producer mode (name) is misconfigured or its jar absent; SPI descriptor missing the name=impl mapping.
Related errors
- Extension instance(name: {}, class: {}) could not be instan
- Extension name == null
- more than 1 default extension name on extension ${type.getNa
- Error when load extension class(interface: ${type}, class li
- Duplicate extension ${type.getName()} name ${n} on ${c.getNa
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/6d76c3b5820f5872.
Report an issue: GitHub.