{"record":{"id":"d12578a4009128d8","repo":"alibaba/canal","slug":"duplicate-extension-type-getname-name-n-on","errorCode":null,"errorMessage":"Duplicate extension ${type.getName()} name ${n} on ${c.getName()} and ${clazz.getName()}","messagePattern":"Duplicate extension (.+?) name (.+?) on (.+?) and (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"connector/core/src/main/java/com/alibaba/otter/canal/connector/core/spi/ExtensionLoader.java","lineNumber":370,"sourceCode":"                                                                                + clazz.getName()\n                                                                                + \"is not subtype of interface.\");\n                                            } else {\n                                                try {\n                                                    clazz.getConstructor(type);\n                                                } catch (NoSuchMethodException e) {\n                                                    clazz.getConstructor();\n                                                    String[] names = NAME_SEPARATOR.split(name);\n                                                    if (names != null && names.length > 0) {\n                                                        for (String n : names) {\n                                                            if (!cachedNames.containsKey(clazz)) {\n                                                                cachedNames.put(clazz, n);\n                                                            }\n                                                            Class<?> c = extensionClasses.get(n);\n                                                            if (c == null) {\n                                                                extensionClasses.put(n, clazz);\n                                                            } else if (c != clazz) {\n                                                                cachedNames.remove(clazz);\n                                                                throw new IllegalStateException(\"Duplicate extension \"\n                                                                                                + type.getName()\n                                                                                                + \" name \" + n + \" on \"\n                                                                                                + c.getName() + \" and \"\n                                                                                                + clazz.getName());\n                                                            }\n                                                        }\n                                                    }\n                                                }\n                                            }\n                                        }\n                                    } catch (Throwable t) {\n                                        IllegalStateException e = new IllegalStateException(\"Failed to load extension class(interface: \"\n                                                                                            + type\n                                                                                            + \", class line: \"\n                                                                                            + line\n                                                                                            + \") in \"\n                                                                                            + url\n                                                                                            + \", cause: \"","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/connector/core/src/main/java/com/alibaba/otter/canal/connector/core/spi/ExtensionLoader.java#L352-L388","documentation":"Constructed in loadFile when two DIFFERENT implementation classes are registered under the same name within the extension map (extensionClasses.get(n) != clazz). Like 215, this exception is created then caught by the inner catch(Throwable) at ExtensionLoader.java:381 and stored into 'exceptions' rather than propagated; the duplicate-name entry is removed and the extension may become unavailable, surfacing later as 'could not be found' (209/211).","triggerScenarios":"Two SPI descriptor entries (across META-INF/canal and META-INF/services, or across plugin jars) bind the same name to distinct classes; a custom jar duplicates a name already provided by a built-in jar.","commonSituations":"Dropping a custom producer jar into plugin/ that reuses the name 'rocketmq'/'kafka' already mapped by the bundled connector jar; two versions of the same connector jar present simultaneously.","solutions":["Give your custom implementation a unique name in its SPI descriptor (do not reuse 'rocketmq'/'kafka').","Remove the older/duplicate connector jar so each name maps to exactly one class.","Inspect plugin/ and lib/ for two jars providing the same SPI descriptor entry."],"exampleFix":"# before: two jars both declare\n#   rocketmq=com.alibaba...CanalRocketMQProducer  (built-in)\n#   rocketmq=com.myco.MyRocketProducer            (custom)\n# after (custom jar):\nmy-rocketmq=com.myco.MyRocketProducer","handlingStrategy":"validation","validationCode":"// Detect duplicate names across descriptors before deploying\nMap<String,String> nameToImpl = new HashMap<>();\nfor (String descriptorLine : allDescriptorLines(interfaceType)) {\n    String name = namePart(descriptorLine);\n    String impl = implPart(descriptorLine);\n    if (nameToImpl.containsKey(name) && !nameToImpl.get(name).equals(impl)) {\n        throw new IllegalStateException(\"duplicate SPI name \" + name);\n    }\n    nameToImpl.put(name, impl);\n}","typeGuard":null,"tryCatchPattern":"// NOTE: thrown-and-stored at load time; surfaces later as 'could not be found'.\ntry {\n    loader.getExtension(name, spiDir, standbyDir);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"could not be found\")) {\n        // grep logs: 'Duplicate extension' -> rename custom impl or remove old jar\n    }\n    throw e;\n}","preventionTips":["Give custom implementations unique SPI names.","Do not keep two versions of the same connector jar in plugin/ and lib/."],"tags":["spi","duplicate","classpath","extension-loader"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}