{"record":{"id":"ad9e8b0590ef4ba7","repo":"apache/dubbo","slug":"failed-to-create-adaptive-class-for-interface-ty","errorCode":null,"errorMessage":"Failed to create adaptive class for interface ${type.getName()}: not found url parameter or url attribute in parameters of method ${method.getName()}","messagePattern":"Failed to create adaptive class for interface (.+?): not found url parameter or url attribute in parameters of method (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/extension/AdaptiveClassCodeGenerator.java","lineNumber":401,"sourceCode":"\n        Map<String, Integer> getterReturnUrl = new HashMap<>();\n        // find URL getter method\n        for (int i = 0; i < pts.length; ++i) {\n            for (Method m : pts[i].getMethods()) {\n                String name = m.getName();\n                if ((name.startsWith(\"get\") || name.length() > 3)\n                        && Modifier.isPublic(m.getModifiers())\n                        && !Modifier.isStatic(m.getModifiers())\n                        && m.getParameterTypes().length == 0\n                        && m.getReturnType() == URL.class) {\n                    getterReturnUrl.put(name, i);\n                }\n            }\n        }\n\n        if (getterReturnUrl.size() <= 0) {\n            // getter method not found, throw\n            throw new IllegalStateException(\"Failed to create adaptive class for interface \" + type.getName()\n                    + \": not found url parameter or url attribute in parameters of method \" + method.getName());\n        }\n\n        Integer index = getterReturnUrl.get(\"getUrl\");\n        if (index != null) {\n            return generateGetUrlNullCheck(index, pts[index], \"getUrl\");\n        } else {\n            Map.Entry<String, Integer> entry =\n                    getterReturnUrl.entrySet().iterator().next();\n            return generateGetUrlNullCheck(entry.getValue(), pts[entry.getValue()], entry.getKey());\n        }\n    }\n\n    /**\n     * 1, test if argi is null\n     * 2, test if argi.getXX() returns null\n     * 3, assign url with argi.getXX()\n     */","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/AdaptiveClassCodeGenerator.java#L383-L419","documentation":"Thrown by AdaptiveClassCodeGenerator during class generation when a @Adaptive method has no URL-typed parameter AND no parameter with a getter method returning URL. The adaptive mechanism needs a URL to resolve the extension name; if it cannot find one directly or indirectly via getXxxUrl(), generation fails. The error names the interface and the offending method.","triggerScenarios":"A @Adaptive method on an SPI interface whose parameter list contains neither a direct URL argument nor any argument exposing a URL via a public no-arg getter returning URL (e.g. getUrl()). Happens during getAdaptiveExtension() at startup.","commonSituations":"Designing a custom @Adaptive method with parameters that don't include URL or a URL-carrier object. Common when adapting an SPI from another framework whose parameter objects don't expose a Dubbo URL. Also happens if a wrapper object's getUrl() method was renamed or its return type changed away from URL.","solutions":["Add a URL-typed parameter to the @Adaptive method, or","Add a public no-arg getter returning org.apache.dubbo.common.URL to one of the parameter types (e.g. getUrl() on a context object)."],"exampleFix":"// before\n@Adaptive\nString doWork(String config);\n\n// after\n@Adaptive\nString doWork(URL url, String config);","handlingStrategy":"validation","validationCode":"boolean hasUrlParam = Arrays.stream(method.getParameterTypes())\n    .anyMatch(p -> p == URL.class);\nboolean hasUrlGetter = Arrays.stream(method.getParameterTypes())\n    .flatMap(p -> Arrays.stream(p.getMethods()))\n    .anyMatch(m -> m.getReturnType() == URL.class && m.getParameterCount() == 0);\nif (!hasUrlParam && !hasUrlGetter) {\n    // this @Adaptive method will fail code generation\n}","typeGuard":"static boolean adaptiveMethodHasUrl(Method method) {\n    Class<?>[] params = method.getParameterTypes();\n    boolean directUrl = Arrays.asList(params).contains(URL.class);\n    boolean indirectUrl = Arrays.stream(params)\n        .flatMap(p -> Arrays.stream(p.getMethods()))\n        .anyMatch(m -> m.getReturnType() == URL.class\n            && Modifier.isPublic(m.getModifiers())\n            && !Modifier.isStatic(m.getModifiers())\n            && m.getParameterCount() == 0);\n    return directUrl || indirectUrl;\n}","tryCatchPattern":null,"preventionTips":["Every @Adaptive method must accept a URL or an object with a URL-returning getter.","Design SPI interfaces with URL parameters on adaptive methods.","Test getAdaptiveExtension() early in development to catch design errors."],"tags":["spi","adaptive-extension","code-generation","url","startup"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}