{"record":{"id":"ab2b24596cea5d26","repo":"apache/maven","slug":"error-evaluating-plugin-parameter-expression-ex-ab2b24","errorCode":null,"errorMessage":"Error evaluating plugin parameter expression: ${expression}","messagePattern":"Error evaluating plugin parameter expression: (.+?)","errorType":"exception","errorClass":"ExpressionEvaluationException","httpStatus":null,"severity":"error","filePath":"impl/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorV4.java","lineNumber":161,"sourceCode":"                try {\n                    int pathSeparator = expression.indexOf('/');\n                    if (pathSeparator > 0) {\n                        String pathExpression = expression.substring(0, pathSeparator);\n                        value = ReflectionValueExtractor.evaluate(pathExpression, ctx.getValue());\n                        if (pathSeparator < expression.length() - 1) {\n                            if (value instanceof Path path) {\n                                value = path.resolve(expression.substring(pathSeparator + 1));\n                            } else {\n                                value = value + expression.substring(pathSeparator);\n                            }\n                        }\n                    } else {\n                        value = ReflectionValueExtractor.evaluate(expression, ctx.getValue());\n                    }\n                    break;\n                } catch (Exception e) {\n                    // TODO don't catch exception\n                    throw new ExpressionEvaluationException(\n                            \"Error evaluating plugin parameter expression: \" + expression, e);\n                }\n            }\n        }\n\n        /*\n         * MNG-4312: We neither have reserved all of the above magic expressions nor is their set fixed/well-known (it\n         * gets occasionally extended by newer Maven versions). This imposes the risk for existing plugins to\n         * unintentionally use such a magic expression for an ordinary property. So here we check whether we\n         * ended up with a magic value that is not compatible with the type of the configured mojo parameter (a string\n         * could still be converted by the configurator so we leave those alone). If so, back off to evaluating the\n         * expression from properties only.\n         */\n        if (value != null && type != null && !(value instanceof String) && !isTypeCompatible(type, value)) {\n            value = null;\n        }\n\n        if (value == null) {","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/apache/maven/blob/e4093d4e120eac99d6bdce5ba67cace2f3085c97/impl/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorV4.java#L143-L179","documentation":"The Maven 4 evaluator (PluginParameterExpressionEvaluatorV4) resolves the expression against the consumer-POM model context (ctx.getValue(), typically the org.apache.maven.api Project or Session) and that reflective evaluation threw. It is the same ExpressionEvaluationException family, but rooted in the new consumer-API objects whose getter surface differs from the legacy MavenProject/Settings.","triggerScenarios":"An expression that resolves on the legacy model but points at a property missing on the v4 consumer model; a nested path traversing a null intermediate on the v4 object graph; expressions referencing build-time-only data stripped from the consumer POM.","commonSituations":"Plugins migrated to the Maven 4 API; builds where the consumer POM no longer carries elements (distribution, development ids) that the expression expects; mixed 3.x/4.x expression behavior.","solutions":["Check the path against the org.apache.maven.api model interfaces (Project, Session, Settings) rather than the legacy classes.","Move custom data you need in expressions into user properties (-D) or <properties>, which survive consumer-POM processing.","Test with mvn help:evaluate -DforceStdout under the same Maven major version you build with.","Avoid deep chains; reference only first- or second-level getters."],"exampleFix":"<!-- before: legacy-only path, absent on the Maven 4 consumer Project -->\n<value>${project.model.build}</value>\n<!-- after: use the consumer-model surface or a property -->\n<value>${project.build.directory}</value>","handlingStrategy":"validation","validationCode":"mvn -q org.apache.maven.plugins:maven-help-plugin:3.4.1:evaluate \\\n  -Dexpression=project.build.directory -DforceStdout || echo 'BAD EXPRESSION'","typeGuard":null,"tryCatchPattern":"try {\n    v = evaluatorV4.evaluate(expr, String.class);\n} catch (ExpressionEvaluationException e) {\n    // fall back to a plain user property so builds stay reproducible across model versions\n    v = session.getUserProperties().getProperty(expr.replaceAll(\"[^a-zA-Z0-9.]\", \"\"));\n}","preventionTips":["Check expressions against org.apache.maven.api model interfaces, not legacy MavenProject","Move data you reference in expressions into user properties to survive consumer-POM processing","Test POMs with mvn help:evaluate under the same Maven major version used in CI"],"tags":["maven","expression","maven4","consumer-pom","reflection"],"backgroundTag":"maven-expression-evaluation-failed","analyzedSha":"e4093d4e120eac99d6bdce5ba67cace2f3085c97","analyzedAt":"2026-08-21T22:58:24.034Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}