{"record":{"id":"dabaa44b81d19690","repo":"alibaba/nacos","slug":"ambiguous-methods-mapped-for-request-getrequestu","errorCode":null,"errorMessage":"Ambiguous methods mapped for '{request.getRequestURI()}': {{bestMatch}, {secondBestMatch}}","messagePattern":"Ambiguous methods mapped for '(.+?)': (.+?), (.+?)\\}","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/com/alibaba/nacos/core/code/ControllerMethodsCache.java","lineNumber":189,"sourceCode":"        String httpMethod = request.getMethod();\n        String urlKey = httpMethod + REQUEST_PATH_SEPARATOR\n            + stripContextPath(path, resolveContextPath(request));\n        List<RequestMappingInfo> requestMappingInfos = urlLookup.get(urlKey);\n        if (CollectionUtils.isEmpty(requestMappingInfos)) {\n            return null;\n        }\n        List<RequestMappingInfo> matchedInfo = findMatchedInfo(requestMappingInfos, request);\n        if (CollectionUtils.isEmpty(matchedInfo)) {\n            return null;\n        }\n        RequestMappingInfo bestMatch = matchedInfo.get(0);\n        if (matchedInfo.size() > 1) {\n            RequestMappingInfoComparator comparator = new RequestMappingInfoComparator();\n            matchedInfo.sort(comparator);\n            bestMatch = matchedInfo.get(0);\n            RequestMappingInfo secondBestMatch = matchedInfo.get(1);\n            if (comparator.compare(bestMatch, secondBestMatch) == 0) {\n                throw new IllegalStateException(\n                    \"Ambiguous methods mapped for '\" + request.getRequestURI() + \"': {\" + bestMatch\n                        + \", \"\n                        + secondBestMatch + \"}\");\n            }\n        }\n        return methods.get(bestMatch);\n    }\n    \n    private String resolveContextPath(HttpServletRequest request) {\n        String requestContextPath = request.getContextPath();\n        return StringUtils.isEmpty(requestContextPath) ? EnvUtil.getContextPath()\n            : requestContextPath;\n    }\n    \n    private String stripContextPath(String path, String contextPath) {\n        if (StringUtils.isEmpty(path) || StringUtils.isEmpty(contextPath)) {\n            return path;\n        }","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/core/src/main/java/com/alibaba/nacos/core/code/ControllerMethodsCache.java#L171-L207","documentation":"Thrown by the legacy controller-method resolver when two distinct RequestMappingInfo entries match the same request URL with an equal comparator ranking, so the resolver cannot pick one deterministically. This is an IllegalStateException surfaced only on the deprecated legacy resolver path (nacos.core.controller.legacy-resolver-enabled). It indicates a genuine ambiguous mapping conflict.","triggerScenarios":"Two @RequestMapping/@GetMapping etc. in different (or the same) controllers register mappings that collide for a given URL+params and compare as equal under RequestMappingInfoComparator. Triggered once a request hits that URL and both survive findMatchedInfo.","commonSituations":"Adding a new controller endpoint that duplicates an existing URL; a custom plugin/controller accidentally reusing a Nacos built-in path; upgrading Nacos and a new endpoint shadows an old one; mixing v2 and v3 controllers that bind the same path under the same context.","solutions":["Search the codebase for the colliding path shown in the message and make each mapping unique (distinct path, method, or params).","Disable the legacy resolver (-Dnacos.core.controller.legacy-resolver.enabled=false, the default) so Spring's own RequestMappingHandlerMapping enforces unambiguous mappings at startup instead.","If you added a custom controller, rename/move its @RequestMapping path away from Nacos core paths."],"exampleFix":"// before: ambiguous\n@RestController\nclass Foo {\n  @GetMapping(\"/v3/admin/ns/service\") void a(){}\n}\n// (collides with built-in ServiceControllerV3)\n\n// after: unique path\n@RestController\nclass Foo {\n  @GetMapping(\"/v3/admin/ns/service/ext\") void a(){}\n}","handlingStrategy":"validation","validationCode":"RequestMappingInfoComparator cmp = new RequestMappingInfoComparator();\nif (matchedInfo.size() > 1 && cmp.compare(matchedInfo.get(0), matchedInfo.get(1)) == 0) {\n    // ambiguous: do not call getMethod; report 409 Conflict upstream\n}","typeGuard":null,"tryCatchPattern":"try {\n    controllerMethodsCache.getMethod(request);\n} catch (IllegalStateException e) { /* ambiguous mapping */ }","preventionTips":["Keep mappings unique; run without the legacy resolver (default) so Spring enforces it at startup.","Audit custom controllers for path collisions against Nacos core paths."],"tags":["spring-mvc","controller","ambiguous-mapping","legacy-resolver"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}