{"record":{"id":"35b15e2259f156d4","repo":"apache/dubbo","slug":"input-type-clazz-can-t-be-interface","errorCode":null,"errorMessage":"Input type ${clazz} can't be interface!","messagePattern":"Input type (.+?) can't be interface!","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java","lineNumber":657,"sourceCode":"        return cachedDefaultName;\n    }\n\n    /**\n     * Register new extension via API\n     *\n     * @param name  extension name\n     * @param clazz extension class\n     * @throws IllegalStateException when extension with the same name has already been registered.\n     */\n    public void addExtension(String name, Class<?> clazz) {\n        checkDestroyed();\n        getExtensionClasses(); // load classes\n\n        if (!type.isAssignableFrom(clazz)) {\n            throw new IllegalStateException(\"Input type \" + clazz + \" doesn't implement the Extension \" + type);\n        }\n        if (clazz.isInterface()) {\n            throw new IllegalStateException(\"Input type \" + clazz + \" can't be interface!\");\n        }\n\n        if (!clazz.isAnnotationPresent(Adaptive.class)) {\n            if (StringUtils.isBlank(name)) {\n                throw new IllegalStateException(\"Extension name is blank (Extension \" + type + \")!\");\n            }\n            if (cachedClasses.get().containsKey(name)) {\n                throw new IllegalStateException(\"Extension name \" + name + \" already exists (Extension \" + type + \")!\");\n            }\n\n            cachedNames.put(clazz, name);\n            cachedClasses.get().put(name, clazz);\n        } else {\n            if (cachedAdaptiveClass != null) {\n                throw new IllegalStateException(\"Adaptive Extension already exists (Extension \" + type + \")!\");\n            }\n\n            cachedAdaptiveClass = clazz;","sourceCodeStart":639,"sourceCodeEnd":675,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java#L639-L675","documentation":"Thrown by ExtensionLoader.addExtension(String name, Class<?> clazz) when the provided class is itself an interface. Dubbo SPI extensions must be instantiable concrete classes — interfaces cannot be instantiated. This guard runs after the assignability check, so the type is assignable (e.g., a sub-interface) but not a concrete implementation.","triggerScenarios":"Calling addExtension with an interface class object instead of a concrete implementation. For example, registering a sub-interface of the SPI type, or passing MySpi.class (the SPI interface itself) as an implementation.","commonSituations":"Developer passes the interface type (not annotated @Adaptive) rather than an implementation class. Confusion about the distinction between the extension point and the extension implementation during programmatic registration.","solutions":["Pass a concrete class that implements the SPI interface, not an interface.","If you intended to register an adaptive class, annotate it with @Adaptive and use the adaptive registration branch.","Verify clazz.isInterface() returns false before calling addExtension."],"exampleFix":"// before — registering an interface\nloader.addExtension(\"subspi\", MySubInterface.class);\n\n// after — register a concrete class\nclass MySubImpl implements MySpi { ... }\nloader.addExtension(\"subspi\", MySubImpl.class);","handlingStrategy":"type-guard","validationCode":"if (clazz.isInterface()) {\n    throw new IllegalStateException(\n        clazz + \" is an interface — provide a concrete implementation class\");\n}\nloader.addExtension(name, clazz);","typeGuard":"static boolean isConcreteClass(Class<?> clazz) {\n    return clazz != null && !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers());\n}","tryCatchPattern":null,"preventionTips":["Always pass concrete (non-interface, non-abstract) classes to addExtension.","Use the type guard to filter interface references out before registration."],"tags":["dubbo-spi","type-validation","registration","extension-system"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}