{"record":{"id":"229265c1243f6168","repo":"apache/dubbo","slug":"setservicemodel-is-forbidden-for-serviceaddressurl","errorCode":null,"errorMessage":"setServiceModel is forbidden for ServiceAddressURL","messagePattern":"setServiceModel is forbidden for ServiceAddressURL","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/url/component/ServiceAddressURL.java","lineNumber":225,"sourceCode":"\n    @Override\n    public ScopeModel getScopeModel() {\n        return consumerURL.getScopeModel();\n    }\n\n    @Override\n    public ServiceModel getServiceModel() {\n        return consumerURL.getServiceModel();\n    }\n\n    @Override\n    public URL setScopeModel(ScopeModel scopeModel) {\n        throw new UnsupportedOperationException(\"setScopeModel is forbidden for ServiceAddressURL\");\n    }\n\n    @Override\n    public URL setServiceModel(ServiceModel serviceModel) {\n        throw new UnsupportedOperationException(\"setServiceModel is forbidden for ServiceAddressURL\");\n    }\n\n    /**\n     * ignore consumer url compare.\n     * It's only meaningful for comparing two address urls related to the same consumerURL.\n     *\n     * @param obj\n     * @return\n     */\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (!(obj instanceof ServiceAddressURL)) {","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/ServiceAddressURL.java#L207-L243","documentation":"UnsupportedOperationException thrown by ServiceAddressURL.setServiceModel() for the same architectural reason as setScopeModel(): ServiceAddressURL delegates getServiceModel() to its wrapped consumerURL, and the service model is owned by the consumer side, not the address. Mutating it on the address URL is forbidden. Callers must operate on the consumerURL directly.","triggerScenarios":"Calling setServiceModel() on a ServiceAddressURL instance. This URL type is created internally during provider address resolution. Framework or application code that generically sets the service model on any URL reference will encounter this if the URL is a ServiceAddressURL.","commonSituations":"Generic URL manipulation code in custom filters, SPI extensions, or interceptors that calls setServiceModel() without type discrimination; Dubbo 2.x-to-3.x migration where address URLs became immutable for service model; code that walks URL chains and tries to set properties uniformly.","solutions":["Do not call setServiceModel() on ServiceAddressURL — set it on the consumer URL via getConsumerURL().","Guard the call with an instanceof check and redirect to the consumer URL for ServiceAddressURL instances.","Audit custom extension code for blanket URL mutation and make it respect the ServiceAddressURL contract."],"exampleFix":"// before — generic mutation fails on ServiceAddressURL\nurl.setServiceModel(serviceModel); // throws if url is ServiceAddressURL\n\n// after — set on the appropriate URL\nif (url instanceof ServiceAddressURL) {\n    ((ServiceAddressURL) url).getConsumerURL().setServiceModel(serviceModel);\n} else {\n    url.setServiceModel(serviceModel);\n}","handlingStrategy":"type-guard","validationCode":"// Check URL type before calling setServiceModel\nif (url instanceof ServiceAddressURL) {\n    ((ServiceAddressURL) url).getConsumerURL().setServiceModel(serviceModel);\n} else {\n    url.setServiceModel(serviceModel);\n}","typeGuard":"public static boolean isMutableServiceModel(URL url) {\n    return !(url instanceof ServiceAddressURL);\n}","tryCatchPattern":"try {\n    url.setServiceModel(serviceModel);\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage().contains(\"forbidden for ServiceAddressURL\")) {\n        if (url instanceof ServiceAddressURL) {\n            ((ServiceAddressURL) url).getConsumerURL().setServiceModel(serviceModel);\n        }\n    } else {\n        throw e;\n    }\n}","preventionTips":["Check url instanceof ServiceAddressURL before calling setServiceModel() on any URL.","Set service model on the consumer URL (getConsumerURL()), not on address URLs.","Make generic URL-processing code aware of ServiceAddressURL's immutability contract.","When migrating to Dubbo 3.x, review all setServiceModel/ setScopeModel call sites."],"tags":["url","immutability","service-model","architecture","dubbo3"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}