apache/maven · error · IntrospectionException

The token '%s' at position '%d' refers to a java.util.Map, b

Error message

The token '%s' at position '%d' refers to a java.util.Map, but the value seems is an instance of '%s'

What it means

ReflectionValueExtractor evaluates POM expressions like ${project.properties.x} by walking object graphs. When a dotted token is dereferenced as a map key against an object that is not a java.util.Map, evaluation aborts with IntrospectionException naming the token, its position in the expression, and the actual class found.

Source

Thrown at compat/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/reflection/ReflectionValueExtractor.java:242

    }

    private static Object getMappedValue(
            final String expression, final int from, final int to, final Object value, final String key)
            throws IntrospectionException {
        if (value == null || key == null) {
            return null;
        }

        if (value instanceof Map map) {
            return map.get(key);
        }

        final String message = String.format(
                "The token '%s' at position '%d' refers to a java.util.Map, but the value "
                        + "seems is an instance of '%s'",
                expression.subSequence(from, to), from, value.getClass());

        throw new IntrospectionException(message);
    }

    private static Object getIndexedValue(
            final String expression, final int from, final int to, final Object value, final String indexStr)
            throws IntrospectionException {
        try {
            int index = Integer.parseInt(indexStr);

            if (value.getClass().isArray()) {
                return Array.get(value, index);
            }

            if (value instanceof List list) {
                return list.get(index);
            }
        } catch (NumberFormatException | IndexOutOfBoundsException e) {
            return null;
        }

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Fix the expression path to match the real structure: use property names on beans, map keys only on Map-valued fields
  2. Reserve dotted-key lookups for genuine Map values such as ${project.properties.someKey}
  3. Search the POM and plugin configuration for the exact token named in the message
  4. Prefer explicit <properties> entries for values you interpolate

Example fix

<!-- before: dotted-key lookup onto a non-Map value -->
<version>${project.dependencyManagement.someKey}</version>

<!-- after: use real map-valued entries for key lookups -->
<version>${project.properties.someKey}</version>
Defensive patterns

Strategy: try-catch

Type guard

static boolean isMapPath(Object node, String key) {
    return node instanceof Map<?, ?> m && m.containsKey(key);
}

Try / catch

try {
    Object v = ReflectionValueExtractor.evaluate(expr, model);
} catch (IntrospectionException e) {
    // e.getMessage() names the token, position, and actual class: treat as config bug
    log.warn("Unusable POM expression {}: {}", expr, e.getMessage());
    return defaultValue; // or rethrow for user-facing validation
}

Prevention

When it happens

Trigger: An expression in a POM or plugin configuration whose intermediate value is a bean but is dereferenced with .key map syntax, e.g. ${project.someBean.someKey} where someBean is not a Map.

Common situations: Expressions written for old POM fields whose type changed; typos after model refactors; plugins interpolating against custom objects with map-style paths.

Related errors


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