apache/maven · error · IllegalStateException

Expected type from key {} to be parameterized

Error message

Expected type from key {} to be parameterized

What it means

Key.getTypeParameter(int) extracts a type argument of the key's underlying java.lang.reflect.Type (the String in List<String>). If the type is not a ParameterizedType — the key was built from a raw class and carries no generic arguments — it throws IllegalStateException. The injector itself calls this while compiling List and Map dependencies, so the error usually surfaces from getInstance/getCompiledBinding.

Source

Thrown at impl/maven-di/src/main/java/org/apache/maven/di/Key.java:149

    /**
     * A shortcut for <code>{@link Types#getRawType(Type)}(key.getType())</code>.
     * Also casts the result to a properly parameterized class.
     */
    @SuppressWarnings("unchecked")
    public Class<T> getRawType() {
        return (Class<T>) Types.getRawType(type);
    }

    /**
     * Returns a type parameter of the underlying type wrapped as a key with no qualifier.
     *
     * @throws IllegalStateException when underlying type is not a parameterized one.
     */
    public <U> Key<U> getTypeParameter(int index) {
        if (type instanceof ParameterizedType parameterizedType) {
            return new KeyImpl<>(parameterizedType.getActualTypeArguments()[index], null);
        }
        throw new IllegalStateException("Expected type from key " + getDisplayString() + " to be parameterized");
    }

    /**
     * Returns the qualifier associated with this key, if any.
     *
     * @return the qualifier object or null if none exists
     */
    public @Nullable Object getQualifier() {
        return qualifier;
    }

    /**
     * Returns an underlying type with display string formatting (package names stripped)
     * and prepended qualifier display string if this key has a qualifier.
     */
    public String getDisplayString() {
        StringBuilder result = new StringBuilder();
        if (qualifier instanceof String s) {

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Build the key from a parameterized type so reflection retains the element type (TypeReference-style or a Key.ofType/ParameterizedType construction)
  2. Inject the concrete element type instead of a raw List or Map
  3. Check the key is parameterized before requesting or extracting type parameters

Example fix

// before
List<Object> all = injector.getInstance(Key.of(List.class)); // raw key -> IllegalStateException

// after
// construct the key from a parameterized List<MyService> type so getTypeParameter(0) can resolve MyService
List<MyService> all = injector.getInstance(listOfMyServiceKey);
Defensive patterns

Strategy: type-guard

Type guard

static boolean isParameterized(Key<?> key) {
    return key.getType() instanceof java.lang.reflect.ParameterizedType;
}

Try / catch

if (!isParameterized(key)) {
    throw new IllegalArgumentException("key must be parameterized, got " + key.getDisplayString());
}
key.getTypeParameter(0);

Prevention

When it happens

Trigger: Requesting a raw generic type from the injector, e.g. getInstance(Key.of(List.class)); requesting a Map key whose arguments are not <String, X>; or calling getTypeParameter directly on a key built from a raw class.

Common situations: Refactorings that drop the type argument from an injection point; registering bindings under Class<List> instead of List<Foo>; hand-built keys that erase generic type information.

Related errors


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