{"record":{"id":"70b9e2c523f85128","repo":"apache/dubbo","slug":"more-than-1-default-extension-name-on-extension","errorCode":null,"errorMessage":"More than 1 default extension name on extension {}: {}","messagePattern":"More than 1 default extension name on extension (.+?): (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java","lineNumber":1036,"sourceCode":"\n            }\n        }\n    }\n\n    /**\n     * extract and cache default extension name if exists\n     */\n    private void cacheDefaultExtensionName() {\n        final SPI defaultAnnotation = type.getAnnotation(SPI.class);\n        if (defaultAnnotation == null) {\n            return;\n        }\n\n        String value = defaultAnnotation.value();\n        if ((value = value.trim()).length() > 0) {\n            String[] names = NAME_SEPARATOR.split(value);\n            if (names.length > 1) {\n                throw new IllegalStateException(\"More than 1 default extension name on extension \" + type.getName()\n                        + \": \" + Arrays.toString(names));\n            }\n            if (names.length == 1) {\n                cachedDefaultName = names[0];\n            }\n        }\n    }\n\n    private void loadDirectoryInternal(\n            Map<String, Class<?>> extensionClasses, LoadingStrategy loadingStrategy, String type)\n            throws InterruptedException {\n        String fileName = loadingStrategy.directory() + type;\n        try {\n            List<ClassLoader> classLoadersToLoad = new LinkedList<>();\n\n            // try to load from ExtensionLoader's ClassLoader first\n            if (loadingStrategy.preferExtensionClassLoader()) {\n                ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();","sourceCodeStart":1018,"sourceCodeEnd":1054,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java#L1018-L1054","documentation":"Thrown by cacheDefaultExtensionName() when the @SPI annotation's value() on an SPI interface contains more than one comma-separated name after trimming. The @SPI annotation declares the default extension name; Dubbo only allows exactly one default. A value like @SPI(\"a,b\") is rejected because getDefaultExtension() cannot resolve ambiguity.","triggerScenarios":"An SPI interface is annotated with @SPI containing multiple names, e.g. @SPI(\"dubbo,mock\") or @SPI(\"a,b,c\"). cacheDefaultExtensionName() is called during the first extension-class load and splits on NAME_SEPARATOR (comma); if more than one token results, it throws immediately.","commonSituations":"A custom SPI interface mistakenly lists multiple defaults; copy-paste from an example that intended multiple Activate values (which use different semantics); a fork that changed a single-default @SPI to list fallbacks thinking it would be tried in order.","solutions":["Edit the SPI interface annotation to contain exactly one default name: @SPI(\"singleName\").","If you need conditional/multiple extension selection, use @Activate annotations on implementations or select by name explicitly via getExtension(name) instead of relying on a default.","If you intended round-robin or fallback, implement a custom selector rather than abusing the default."],"exampleFix":"// before\n@SPI(\"dubbo,rest\")\npublic interface Protocol { ... }\n// throws [145] at load time\n\n// after\n@SPI(\"dubbo\")\npublic interface Protocol { ... }","handlingStrategy":"validation","validationCode":"// Validate the @SPI annotation at build/test time\nSPI ann = MySpi.class.getAnnotation(SPI.class);\nif (ann != null) {\n    String[] names = ann.value().trim().split(\",\");\n    if (names.length > 1) throw new IllegalStateException(\"@SPI has multiple defaults: \" + ann.value());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Annotate SPI interfaces with exactly one default name in @SPI.","Add a unit test asserting the @SPI value has at most one comma-separated token.","Use @Activate for conditional multi-extension selection instead of multi-default @SPI."],"tags":["dubbo-spi","spi-annotation","config","startup","extension-loader"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}