alibaba/nacos · error · IllegalStateException
Ambiguous methods mapped for '{request.getRequestURI()}': {{
Error message
Ambiguous methods mapped for '{request.getRequestURI()}': {{bestMatch}, {secondBestMatch}} What it means
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.
Source
Thrown at core/src/main/java/com/alibaba/nacos/core/code/ControllerMethodsCache.java:189
String httpMethod = request.getMethod();
String urlKey = httpMethod + REQUEST_PATH_SEPARATOR
+ stripContextPath(path, resolveContextPath(request));
List<RequestMappingInfo> requestMappingInfos = urlLookup.get(urlKey);
if (CollectionUtils.isEmpty(requestMappingInfos)) {
return null;
}
List<RequestMappingInfo> matchedInfo = findMatchedInfo(requestMappingInfos, request);
if (CollectionUtils.isEmpty(matchedInfo)) {
return null;
}
RequestMappingInfo bestMatch = matchedInfo.get(0);
if (matchedInfo.size() > 1) {
RequestMappingInfoComparator comparator = new RequestMappingInfoComparator();
matchedInfo.sort(comparator);
bestMatch = matchedInfo.get(0);
RequestMappingInfo secondBestMatch = matchedInfo.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
throw new IllegalStateException(
"Ambiguous methods mapped for '" + request.getRequestURI() + "': {" + bestMatch
+ ", "
+ secondBestMatch + "}");
}
}
return methods.get(bestMatch);
}
private String resolveContextPath(HttpServletRequest request) {
String requestContextPath = request.getContextPath();
return StringUtils.isEmpty(requestContextPath) ? EnvUtil.getContextPath()
: requestContextPath;
}
private String stripContextPath(String path, String contextPath) {
if (StringUtils.isEmpty(path) || StringUtils.isEmpty(contextPath)) {
return path;
}View on GitHub (pinned to 9b989acdf1)
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.
Example fix
// before: ambiguous
@RestController
class Foo {
@GetMapping("/v3/admin/ns/service") void a(){}
}
// (collides with built-in ServiceControllerV3)
// after: unique path
@RestController
class Foo {
@GetMapping("/v3/admin/ns/service/ext") void a(){}
} Defensive patterns
Strategy: validation
Validate before calling
RequestMappingInfoComparator cmp = new RequestMappingInfoComparator();
if (matchedInfo.size() > 1 && cmp.compare(matchedInfo.get(0), matchedInfo.get(1)) == 0) {
// ambiguous: do not call getMethod; report 409 Conflict upstream
} Try / catch
try {
controllerMethodsCache.getMethod(request);
} catch (IllegalStateException e) { /* ambiguous mapping */ } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/dabaa44b81d19690.
Report an issue: GitHub.