{"record":{"id":"bcbafd771feec3cf","repo":"alibaba/canal","slug":"extension-instance-name-class-could-not-bcbafd","errorCode":null,"errorMessage":"Extension instance(name: {}, class: {})  could not be instantiated: class could not be found","messagePattern":"Extension instance\\(name: (.+?), class: (.+?)\\)  could not be instantiated: class could not be found","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"connector/core/src/main/java/com/alibaba/otter/canal/connector/core/spi/ExtensionLoader.java","lineNumber":169,"sourceCode":"        return (T) instance;\n    }\n\n    /**\n     * 返回缺省的扩展，如果没有设置则返回<code>null</code>\n     */\n    public T getDefaultExtension(String spiDir, String standbyDir) {\n        getExtensionClasses(spiDir, standbyDir);\n        if (null == cachedDefaultName || cachedDefaultName.length() == 0 || \"true\".equals(cachedDefaultName)) {\n            return null;\n        }\n        return getExtension(cachedDefaultName, spiDir, standbyDir);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public T createExtension(String name, String spiDir, String standbyDir) {\n        Class<?> clazz = getExtensionClasses(spiDir, standbyDir).get(name);\n        if (clazz == null) {\n            throw new IllegalStateException(\"Extension instance(name: \" + name + \", class: \" + type\n                                            + \")  could not be instantiated: class could not be found\");\n        }\n        try {\n            T instance = (T) EXTENSION_INSTANCES.get(clazz);\n            if (instance == null) {\n                EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());\n                instance = (T) EXTENSION_INSTANCES.get(clazz);\n            }\n            return instance;\n        } catch (Throwable t) {\n            throw new IllegalStateException(\"Extension instance(name: \" + name + \", class: \" + type\n                                            + \")  could not be instantiated: \" + t.getMessage(), t);\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private T createExtension(String name, String key, String spiDir, String standbyDir) {\n        Class<?> clazz = getExtensionClasses(spiDir, standbyDir).get(name);","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/connector/core/src/main/java/com/alibaba/otter/canal/connector/core/spi/ExtensionLoader.java#L151-L187","documentation":"Thrown by createExtension(name, spiDir, standbyDir) when the requested name is not present in the loaded extension class map (getExtensionClasses().get(name) == null). This means no META-INF/canal/<interface> or META-INF/services/<interface> entry maps that name to a class. It is the canonical 'extension not found' error and also surfaces indirectly when a bad extension was rejected during loading (e.g. subtype/duplicate errors 215/216 that were stored, not thrown, at load time).","triggerScenarios":"Requesting getExtension(\"kafka\") when no 'kafka=com.alibaba...KafkaMQProducer' line exists in the SPI descriptor; the connector jar providing that implementation is not on the classpath/plugin dir; the entry exists but was rejected during load (then silently stored in the exceptions map).","commonSituations":"canal.serverMode/canal.mq.mode set to a producer whose plugin jar is missing from plugin/ or deployer lib; typo in the mode name; SPI descriptor file missing or in the wrong directory (META-INF/canal vs META-INF/services); extension present but failed validation at load (see ExtensionLoader loadFile exceptions map).","solutions":["Verify the producer/connector plugin jar exists under the plugin/ (or standby) directory and is loadable.","Confirm the SPI descriptor META-INF/canal/<fully-qualified-interface> contains a line 'name=implClass' for the requested name.","Check the ExtensionLoader exceptions map / logs ('Exception when load extension class') to see if the entry was rejected during load (subtype mismatch or duplicate), and fix that root cause.","Correct the mode name in config (e.g. 'rocketmq' not 'rocketMQ')."],"exampleFix":"# before\ncanal.serverMode = rocketmqq   # typo, no such extension\n# after\ncanal.serverMode = rocketmq","handlingStrategy":"try-catch","validationCode":"// Pre-check that the name is registered before requesting\njava.util.Map<String,Class<?>> known = reflectRegisteredNames(interfaceType);\nif (!known.containsKey(name)) {\n    throw new IllegalStateException(\n        \"extension '\" + name + \"' not registered; known: \" + known.keySet());\n}\nloader.getExtension(name, spiDir, standbyDir);","typeGuard":null,"tryCatchPattern":"try {\n    return loader.getExtension(name, spiDir, standbyDir);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"could not be found\")) {\n        // name not on classpath: verify plugin jar + descriptor, or fall back\n        throw new IllegalStateException(\n            \"extension '\" + name + \"' missing: check plugin/ jar and \"\n          + \"META-INF/canal/\" + interfaceType.getName(), e);\n    }\n    throw e;\n}","preventionTips":["Ship the connector plugin jar in plugin/ and its META-INF/canal descriptor.","Check load-time logs for rejected entries that silently drop a name.","Validate the mode name spelling against registered names at startup."],"tags":["spi","classpath","extension-loader","config"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}