alibaba/canal · error · IllegalStateException
Error when load extension class(interface: ${type}, class li
Error message
Error when load extension class(interface: ${type}, class line: ${clazz.getName()}), class ${clazz.getName()}is not subtype of interface. What it means
Constructed in loadFile when an SPI descriptor line names a class that does NOT implement/extend the extension interface (type.isAssignableFrom(clazz) is false). IMPORTANT: this exception is created but then caught by the inner catch(Throwable) at ExtensionLoader.java:381 and stored into the 'exceptions' map rather than propagated; the offending class is skipped. The user therefore usually sees a later 'could not be found' (209/211) or a load-time log line, not this message directly.
Source
Thrown at connector/core/src/main/java/com/alibaba/otter/canal/connector/core/spi/ExtensionLoader.java:347
while ((line = reader.readLine()) != null) {
final int ci = line.indexOf('#');
if (ci >= 0) line = line.substring(0, ci);
line = line.trim();
if (line.length() > 0) {
try {
String name = null;
int i = line.indexOf('=');
if (i > 0) {
name = line.substring(0, i).trim();
line = line.substring(i + 1).trim();
}
if (line.length() > 0) {
Class<?> clazz = classLoader.loadClass(line);
// Class<?> clazz =
// Class.forName(line, true,
// classLoader);
if (!type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Error when load extension class(interface: "
+ type
+ ", class line: "
+ clazz.getName()
+ "), class "
+ clazz.getName()
+ "is not subtype of interface.");
} else {
try {
clazz.getConstructor(type);
} catch (NoSuchMethodException e) {
clazz.getConstructor();
String[] names = NAME_SEPARATOR.split(name);
if (names != null && names.length > 0) {
for (String n : names) {
if (!cachedNames.containsKey(clazz)) {
cachedNames.put(clazz, n);
}
Class<?> c = extensionClasses.get(n);View on GitHub (pinned to 87be50e876)
Solutions
- Correct the descriptor line so the class implements the extension interface (verify classpath FQN).
- Check load-time logs ('Exception when load extension class') to identify which line/class was rejected.
- Rebuild/redeploy the plugin jar with the correct implementation-extends-interface relationship.
Example fix
# before (META-INF/canal/...CanalMQProducer) rocketmq=com.alibaba...SomeUnrelatedClass # after rocketmq=com.alibaba.otter.canal.connector.rocketmq.producer.CanalRocketMQProducer
Defensive patterns
Strategy: validation
Validate before calling
// At build/test time, assert every SPI descriptor line maps to a subtype
Class<?> ext = Class.forName(implFqn);
if (!interfaceType.isAssignableFrom(ext)) {
throw new IllegalStateException(ext + " does not implement " + interfaceType);
} Type guard
boolean isSubtypeOf(Class<?> impl, Class<?> iface) {
return impl != null && iface != null && iface.isAssignableFrom(impl);
} Try / catch
// NOTE: thrown-and-stored at load time; surfaces later as 'could not be found'.
// Catch that downstream symptom and inspect logs for the subtype error.
try {
loader.getExtension(name, spiDir, standbyDir);
} catch (IllegalStateException e) {
if (e.getMessage().contains("could not be found")) {
// grep logs: 'is not subtype of interface' -> fix descriptor line
}
throw e;
} Prevention
- Keep SPI descriptor FQNs in sync with implementation renames/repackages.
- Add a test that loads each descriptor and asserts type.isAssignableFrom(impl).
When it happens
Trigger: A META-INF/canal/<interface> descriptor maps a name to a class that is not a subtype of the extension interface (wrong class, stale FQN after a rename, copy-paste from another interface's descriptor).
Common situations: Renaming/repackaging an implementation without updating its SPI descriptor line; descriptor line referencing a class that implements a sibling interface; vendor jar shipping an incompatible implementation version.
Related errors
- Extension instance(name: {}, class: {}) could not be instan
- Extension instance(name: ${name}, class: ${type}) could not
- Duplicate extension ${type.getName()} name ${n} on ${c.getNa
- Extension type == null
- Extension type({}) is not interface!
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/b7921d048ad7cff1.
Report an issue: GitHub.