apache/maven · error · ExpressionEvaluationException

Error evaluating plugin parameter expression: ${expression}

Error message

Error evaluating plugin parameter expression: ${expression}

What it means

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.

Source

Thrown at impl/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorV4.java:161

                try {
                    int pathSeparator = expression.indexOf('/');
                    if (pathSeparator > 0) {
                        String pathExpression = expression.substring(0, pathSeparator);
                        value = ReflectionValueExtractor.evaluate(pathExpression, ctx.getValue());
                        if (pathSeparator < expression.length() - 1) {
                            if (value instanceof Path path) {
                                value = path.resolve(expression.substring(pathSeparator + 1));
                            } else {
                                value = value + expression.substring(pathSeparator);
                            }
                        }
                    } else {
                        value = ReflectionValueExtractor.evaluate(expression, ctx.getValue());
                    }
                    break;
                } catch (Exception e) {
                    // TODO don't catch exception
                    throw new ExpressionEvaluationException(
                            "Error evaluating plugin parameter expression: " + expression, e);
                }
            }
        }

        /*
         * MNG-4312: We neither have reserved all of the above magic expressions nor is their set fixed/well-known (it
         * gets occasionally extended by newer Maven versions). This imposes the risk for existing plugins to
         * unintentionally use such a magic expression for an ordinary property. So here we check whether we
         * ended up with a magic value that is not compatible with the type of the configured mojo parameter (a string
         * could still be converted by the configurator so we leave those alone). If so, back off to evaluating the
         * expression from properties only.
         */
        if (value != null && type != null && !(value instanceof String) && !isTypeCompatible(type, value)) {
            value = null;
        }

        if (value == null) {

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Check the path against the org.apache.maven.api model interfaces (Project, Session, Settings) rather than the legacy classes.
  2. Move custom data you need in expressions into user properties (-D) or <properties>, which survive consumer-POM processing.
  3. Test with mvn help:evaluate -DforceStdout under the same Maven major version you build with.
  4. Avoid deep chains; reference only first- or second-level getters.

Example fix

<!-- before: legacy-only path, absent on the Maven 4 consumer Project -->
<value>${project.model.build}</value>
<!-- after: use the consumer-model surface or a property -->
<value>${project.build.directory}</value>
Defensive patterns

Strategy: validation

Validate before calling

mvn -q org.apache.maven.plugins:maven-help-plugin:3.4.1:evaluate \
  -Dexpression=project.build.directory -DforceStdout || echo 'BAD EXPRESSION'

Try / catch

try {
    v = evaluatorV4.evaluate(expr, String.class);
} catch (ExpressionEvaluationException e) {
    // fall back to a plain user property so builds stay reproducible across model versions
    v = session.getUserProperties().getProperty(expr.replaceAll("[^a-zA-Z0-9.]", ""));
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21). Data as JSON: /api/errors/ab2b24596cea5d26. Report an issue: GitHub.