{"record":{"id":"ba912bf8f2e7b7c7","repo":"apache/shenyu","slug":"load-extension-resources-error-duplicate-class-clazz-name","errorCode":null,"errorMessage":"load extension resources error,Duplicate class clazz name name on oldClass or subClass","messagePattern":"load extension resources error,Duplicate class clazz name name on oldClass or subClass","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"shenyu-spi/src/main/java/org/apache/shenyu/spi/ExtensionLoader.java","lineNumber":319,"sourceCode":"        }\n    }\n    \n    private void loadClass(final Map<String, ClassEntity> classes,\n                           final String name, final String classPath) throws ClassNotFoundException {\n        Class<?> subClass = Objects.nonNull(this.classLoader) ? Class.forName(classPath, true, this.classLoader) : Class.forName(classPath);\n        if (!clazz.isAssignableFrom(subClass)) {\n            throw new IllegalStateException(\"load extension resources error,\" + subClass + \" subtype is not of \" + clazz);\n        }\n        if (!subClass.isAnnotationPresent(Join.class)) {\n            throw new IllegalStateException(\"load extension resources error,\" + subClass + \" without @\" + Join.class + \" annotation\");\n        }\n        ClassEntity oldClassEntity = classes.get(name);\n        if (Objects.isNull(oldClassEntity)) {\n            Join joinAnnotation = subClass.getAnnotation(Join.class);\n            ClassEntity classEntity = new ClassEntity(name, joinAnnotation.order(), subClass, joinAnnotation.isSingleton());\n            classes.put(name, classEntity);\n        } else if (!Objects.equals(oldClassEntity.getClazz(), subClass)) {\n            throw new IllegalStateException(\"load extension resources error,Duplicate class \" + clazz.getName() + \" name \"\n                    + name + \" on \" + oldClassEntity.getClazz().getName() + \" or \" + subClass.getName());\n        }\n    }\n    \n    /**\n     * The type Holder.\n     *\n     * @param <T> the type parameter.\n     */\n    private static final class Holder<T> {\n        \n        private volatile T value;\n        \n        private Integer order;\n\n        /**\n         * Gets value.\n         *","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-spi/src/main/java/org/apache/shenyu/spi/ExtensionLoader.java#L301-L337","documentation":"ShenYu's SPI ExtensionLoader loads extension implementations from META-INF/shenyu/ resource files, mapping a name to a class. When two different classes claim the same extension name within one extension interface's resources, it cannot decide which one is correct and throws this IllegalStateException during loadResources → loadClass.","triggerScenarios":"Two SPI registration files (or duplicate entries in one file) under META-INF/shenyu/ declare the same extension `name` mapped to different implementation classes of the same @SPI interface.","commonSituations":"Merging upstream code with a locally added extension that reused an existing name; adding a custom implementation in a jar that collides with a ShenYu built-in extension name; copy-pasting an SPI config line without changing the name key.","solutions":["Rename the extension name in your META-INF/shenyu/<interface-fqcn> file so it is unique","Remove the duplicate/conflicting registration line or the redundant jar containing the conflicting implementation","If the classes are actually identical, delete one of the duplicate declarations"],"exampleFix":"// before (META-INF/shenyu/org.apache.shenyu.spi.HttpParamConverter)\ntimeConverter=org.apache.shenyu.example.TimeConverter\n// after (unique name)\nmyTimeConverter=org.apache.shenyu.example.TimeConverter","handlingStrategy":"validation","validationCode":"Map<String,String> names = new HashMap<>();\nfor (String line : Files.readAllLines(spiFile)) {\n    String name = line.split(\"=\", 2)[0].trim();\n    if (names.containsKey(name)) throw new IllegalStateException(\"duplicate SPI name: \" + name);\n    names.put(name, line);\n}","typeGuard":null,"tryCatchPattern":"try {\n    extension = ExtensionLoader.getExtensionLoader(MySpi.class).getJoin(\"myName\");\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"Duplicate class\")) {\n        log.error(\"Conflicting SPI registration for name\", e);\n    } else throw e;\n}","preventionTips":["Prefix custom extension names with your organization/product name","Audit META-INF/shenyu/ files in all jars on the classpath before release","Never reuse an upstream ShenYu extension name for a different class"],"tags":["spi","classpath","duplicate-key","configuration"],"backgroundTag":"file-already-exists","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}