{"record":{"id":"39186dc6003f8f63","repo":"flowable/flowable-engine","slug":"error-function-notfound","errorCode":"error.function.notfound","errorMessage":"error.function.notfound","messagePattern":"error\\.function\\.notfound","errorType":"exception","errorClass":"ELException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/Tree.java","lineNumber":124,"sourceCode":"\tpublic Bindings bind(FunctionMapper fnMapper, VariableMapper varMapper, TypeConverter converter) {\n\t\tMethod[] methods = null;\n\t\tif (!functions.isEmpty()) {\n\t\t\tif (fnMapper == null) {\n\t\t\t\tthrow new ELException(LocalMessages.get(\"error.function.nomapper\"));\n\t\t\t}\n\t\t\tmethods = new Method[functions.size()];\n\t\t\tfor (int i = 0; i < functions.size(); i++) {\n\t\t\t\tFunctionNode node = functions.get(i);\n\t\t\t\tString image = node.getName();\n\t\t\t\tMethod method = null;\n\t\t\t\tint colon = image.indexOf(':');\n\t\t\t\tif (colon < 0) {\n\t\t\t\t\tmethod = fnMapper.resolveFunction(\"\", image);\n\t\t\t\t} else {\n\t\t\t\t\tmethod = fnMapper.resolveFunction(image.substring(0, colon), image.substring(colon + 1));\n\t\t\t\t}\n\t\t\t\tif (method == null) {\n\t\t\t\t\tthrow new ELException(LocalMessages.get(\"error.function.notfound\", image));\n\t\t\t\t}\n\t\t\t\tif (node.isVarArgs() && method.isVarArgs()) {\n\t\t\t\t\tif (method.getParameterTypes().length > node.getParamCount() + 1) {\n\t\t\t\t\t\tthrow new ELException(LocalMessages.get(\"error.function.params\", image));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (method.getParameterTypes().length != node.getParamCount()) {\n\t\t\t\t\t\tthrow new ELException(LocalMessages.get(\"error.function.params\", image));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmethods[node.getIndex()] = method;\n\t\t\t}\n\t\t}\n\t\tValueExpression[] expressions = null;\n\t\tif (identifiers.size() > 0) {\n\t\t\texpressions = new ValueExpression[identifiers.size()];\n\t\t\tfor (int i = 0; i < identifiers.size(); i++) {\n\t\t\t\tIdentifierNode node = identifiers.get(i);","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/Tree.java#L106-L142","documentation":"Tree.bind() asked the FunctionMapper to resolve a function named in the expression and got null back: no Method is registered under that prefix/local name. JUEL throws ELException error.function.notfound naming the function image (e.g. 'my:check').","triggerScenarios":"An expression contains ns:name(...) but the FunctionMapper.resolveFunction returns null — the function bean/method is not registered, the prefix is wrong, or the mapper used at bind time differs from the one configured with the functions.","commonSituations":"Flowable custom function beans not exposed via the function delegate; typo in function name or namespace in the expression; functions available in one engine/module but used in expressions of another; classpath/config changes dropping the function registration.","solutions":["Register the missing function with the FunctionMapper / Flowable function delegates so resolveFunction returns the Method.","Fix the function name/prefix typo in the expression.","Verify at startup that every function used in deployed expressions resolves via the mapper.","Catch ELException, parse the function image from the message, and report which function is unregistered."],"exampleFix":"// before\n// expression uses ${acct:balance(id)} but no 'acct' functions registered -> ELException\n// after\nfunctionMapper.mapFunction(\"acct\", \"balance\",\n    AccountFunctions.class.getMethod(\"balance\", Long.class));","handlingStrategy":"validation","validationCode":"Set<String> registered = loadedFunctionNames(functionMapper); // names your mapper resolves\nfor (String fn : extractFunctionImages(expression)) { // regex: ([\\w]+):([\\w]+)\\(\n    if (!registered.contains(fn)) throw new IllegalStateException(\"Unregistered EL function: \" + fn);\n}","typeGuard":null,"tryCatchPattern":"try {\n    bindings = tree.bind(fnMapper, varMapper, converter);\n} catch (ELException e) {\n    log.error(\"Unknown EL function in '{}': {}\", expression, e.getMessage(), e);\n    throw new ConfigurationException(e.getMessage(), e);\n}","preventionTips":["Register all custom functions with the FunctionMapper at engine startup.","Keep a registry/test asserting every function used in deployed expressions resolves.","Avoid renaming function namespaces without migrating expressions.","Validate expressions as part of deployment (parse+bind dry run)."],"tags":["el","function-not-found","expression-binding"],"backgroundTag":"method-not-found","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"}