{"record":{"id":"3b88f2d26161f309","repo":"flowable/flowable-engine","slug":"error-function-access","errorCode":null,"errorMessage":"error.function.access","messagePattern":"error\\.function\\.access","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/impl/ast/AstFunction.java","lineNumber":121,"sourceCode":"\t\t\t} else {\n\t\t\t\tfor (int i = 0; i < params.length; i++) {\n\t\t\t\t\tObject param = getParam(i).eval(bindings, context);\n\t\t\t\t\tif (param != null || types[i].isPrimitive()) {\n\t\t\t\t\t\tparams[i] = bindings.convert(param, types[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn method.invoke(base, params);\n\t}\n\n\t@Override \n\tpublic Object eval(Bindings bindings, ELContext context) {\n\t\tMethod method = bindings.getFunction(index);\n\t\ttry {\n\t\t\treturn invoke(bindings, context, null, method);\n\t\t} catch (IllegalAccessException e) {\n\t\t\tthrow new ELException(LocalMessages.get(\"error.function.access\", name), e);\n\t\t} catch (InvocationTargetException e) {\n\t\t\tthrow new ELException(LocalMessages.get(\"error.function.invocation\", name), e.getCause());\n\t\t}\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn name;\n\t}\t\n\n\t@Override \n\tpublic void appendStructure(StringBuilder b, Bindings bindings) {\n\t\tb.append(bindings != null && bindings.isFunctionBound(index) ? \"<fn>\" : name);\n\t\tparams.appendStructure(b, bindings);\n\t}\n\n\t@Override\n\tpublic int getIndex() {","sourceCodeStart":103,"sourceCodeEnd":139,"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/impl/ast/AstFunction.java#L103-L139","documentation":"AstFunction.eval() invokes the bound EL function via reflection. If the reflected Method is inaccessible from the EL context (IllegalAccessException — e.g. the method or its class is not public, or package-private and blocked by module/access restrictions), the failure is wrapped in ELException with message 'error.function.access: <functionName>'.","triggerScenarios":"Registering an EL function whose implementing Method is non-public (private/protected/package-private), or public method in a non-exported package (JPMS), then evaluating an expression that calls the function (e.g. ${myfn:check(x)}).","commonSituations":"Function libraries registered via ExpressionFactory/function mappings pointing at utility classes with non-public methods; Java 9+ module encapsulation hiding reflection targets; shaded/relocated classes in fat jars breaking accessibility.","solutions":["Make the function method and its declaring class public.","Verify the function mapping in the ExpressionFactory/config points at the correct class and method name.","With JPMS, open/export the package to the EL implementation module.","Catch ELException around expression evaluation and log getRootCause()/getCause() (the IllegalAccessException) to identify the inaccessible method."],"exampleFix":"// before\nclass Fns { static boolean check(int x) { ... } } // package-private\n// after\npublic class Fns { public static boolean check(int x) { ... } }","handlingStrategy":"try-catch","validationCode":"// verify function accessibility before registering\nMethod m = clazz.getMethod(name, paramTypes);\nif (!Modifier.isPublic(m.getModifiers()) || !Modifier.isPublic(clazz.getModifiers()))\n    throw new IllegalArgumentException(\"EL function must be public: \" + name);","typeGuard":null,"tryCatchPattern":"try {\n    return valueExpression.getValue(context);\n} catch (ELException e) {\n    Throwable root = e.getCause();\n    if (root instanceof IllegalAccessException)\n        throw new IllegalStateException(\"EL function not accessible: \" + root.getMessage(), root);\n    throw e;\n}","preventionTips":["Declare EL functions and their classes public.","With JPMS, export/open packages containing function classes.","Check accessibility of every mapped function at application startup.","Beware shading/relocation changing class visibility or names."],"tags":["el","reflection","illegal-access","function"],"backgroundTag":"permission-denied","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}