{"record":{"id":"70a690131a177af3","repo":"flowable/flowable-engine","slug":"unable-to-find-unambiguous-method-clazz-name","errorCode":null,"errorMessage":"Unable to find unambiguous method: ${clazz}.${name}(${paramString(paramTypes)})","messagePattern":"Unable to find unambiguous method: (.+?)\\.(.+?)\\((.+?)\\)","errorType":"exception","errorClass":"MethodNotFoundException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/javax/el/Util.java","lineNumber":255,"sourceCode":"            } else if (cmp == 0) {\n                ambiguousCandidates.add(entry.getKey());\n                multiple = true;\n            }\n        }\n        if (multiple) {\n            if (bestMatch.getExactCount() == paramCount - 1) {\n                // Only one parameter is not an exact match - try using the\n                // super class\n                String errorMsg = \"Unable to find unambiguous method: \" + clazz + \".\" + name + \"(\" + paramString(paramTypes) + \")\";\n                match = findMostSpecificWrapper(ambiguousCandidates, paramTypes, bestMatch.getAssignableCount() > 0, errorMsg);\n            } else {\n                match = null;\n            }\n\n            if (match == null) {\n                // If multiple methods have the same matching number of parameters\n                // the match is ambiguous so throw an exception\n                throw new MethodNotFoundException(\"Unable to find unambiguous method: \" + clazz + \".\" + name + \"(\" + paramString(paramTypes) + \")\");\n            }\n        }\n\n        // Handle case where no match at all was found\n        if (match == null) {\n            throw new MethodNotFoundException(\"Method not found: \" + clazz + \".\" + name + \"(\" + paramString(paramTypes) + \")\");\n        }\n\n        return match;\n    }\n\n    /*\n     * This method duplicates code in com.sun.el.util.ReflectionUtil. When making changes keep the code in sync.\n     */\n    private static <T> Wrapper<T> findMostSpecificWrapper(Collection<Wrapper<T>> candidates, Class<?>[] matchingTypes, boolean elSpecific, String errorMsg) {\n        List<Wrapper<T>> ambiguouses = new ArrayList<>();\n        for (Wrapper<T> candidate : candidates) {\n            boolean lessSpecific = false;","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/javax/el/Util.java#L237-L273","documentation":"Flowable's EL method resolver throws MethodNotFoundException when more than one method on the target class matches the expression's parameter count/types equally, so no unambiguous best match exists. Rather than guessing, the resolver fails fast. This mirrors the ambiguity handling in Tomcat's org.apache.el.util.ReflectionUtil.","triggerScenarios":"Evaluating an EL method expression where the target class has overloaded methods with equal match quality for the supplied argument types, e.g. two overloads both applicable after coercion, reached via Util.findWrapper from Util.result.","commonSituations":"Overloaded service methods (e.g. foo(String) and foo(Integer)) invoked with an EL expression whose argument type is ambiguous (null literal, or a value EL coerces either way); adding an overload to a bean that is also referenced from existing process expressions.","solutions":["Rename one of the ambiguous overloaded methods or use distinct method names in expressions","Cast or coerce the argument explicitly in the expression so exactly one overload matches","Pass arguments whose runtime types unambiguously select a single overload"],"exampleFix":"// before: bean has handle(String) and handle(Integer), expression arg type ambiguous\n${taskService.handle(value)}\n// after: dedicated method avoids ambiguity\n${taskService.handleString(value)}","handlingStrategy":"validation","validationCode":"long matches = Arrays.stream(clazz.getMethods()).filter(m -> m.getName().equals(name) && isApplicable(m, argValues)).count();\nif (matches > 1) throw new IllegalStateException(\"Ambiguous EL method: \" + name);","typeGuard":null,"tryCatchPattern":"try { method = Util.findMethod(context, clazz, base, name, argTypes, args); } catch (MethodNotFoundException e) { if (e.getMessage().startsWith(\"Unable to find unambiguous\")) { log.warn(\"Ambiguous overload for {}\", name); } throw e; }","preventionTips":["Avoid overloaded method names on beans exposed to EL expressions","Pass explicitly typed arguments in expressions","When adding overloads, grep deployed models for existing references"],"tags":["el","expression-language","overload","ambiguity"],"backgroundTag":"invalid-argument-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}