apple/pkl · error · IllegalArgumentException

Expected %d type arguments for `%s`, but got %d.

Error message

Expected %d type arguments for `%s`, but got %d.

What it means

parameterizedType() requires one type argument per declared type parameter of the raw class. Supplying fewer or more arguments than getTypeParameters().length throws with the expected and actual counts.

Source

Thrown at pkl-config-java/src/main/java/org/pkl/config/java/mapper/Types.java:41

import org.pkl.core.Pair;

/**
 * A factory for parameterized type literals such as {@code List<String>} or {@code MyClass<Foo,
 * Bar>}. Used to express the desired target type in {@link ValueMapper#map(Object, Type)}.
 */
public final class Types {
  private Types() {}

  public static ParameterizedType parameterizedType(Class<?> rawType, Type... typeArguments) {
    var typeParamsCount = rawType.getTypeParameters().length;
    if (typeParamsCount == 0) {
      throw new IllegalArgumentException(
          String.format(
              "Cannot parameterize `%s` because it does not have any type parameters.",
              rawType.getTypeName()));
    }
    if (typeArguments.length != typeParamsCount) {
      throw new IllegalArgumentException(
          String.format(
              "Expected %d type arguments for `%s`, but got %d.",
              typeParamsCount, rawType.getTypeName(), typeArguments.length));
    }
    for (Type arg : typeArguments) {
      if (arg instanceof Class<?> clazz) {
        if (clazz.isPrimitive()) {
          throw new IllegalArgumentException(
              String.format(
                  "`%s.class` is not a valid type argument. Did you mean `%s.class`?",
                  clazz, Reflection.toWrapperType(clazz).getSimpleName()));
        }
      }
    }
    try {
      return (ParameterizedType) TypeFactory.parameterizedClass(rawType, typeArguments);
    } catch (TypeArgumentNotInBoundException e) {
      throw new IllegalArgumentException(

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Supply exactly as many type arguments as the raw class declares.
  2. For Map, pass both key and value argument types.
  3. Verify the count against rawType.getTypeParameters().length before calling.

Example fix

// before
Types.parameterizedType(Map.class, String.class);
// after
Types.parameterizedType(Map.class, String.class, Integer.class);
Defensive patterns

Strategy: validation

Validate before calling

if (args.length != rawType.getTypeParameters().length) throw new IllegalArgumentException("wrong number of type arguments");

Type guard

static int expectedArgCount(Class<?> c) { return c.getTypeParameters().length; }

Try / catch

try { Types.parameterizedType(raw, args); } catch (IllegalArgumentException e) { /* correct arity */ }

Prevention

When it happens

Trigger: parameterizedType(Map.class, String.class) (1 arg for 2 params) or parameterizedType(List.class, String.class, Integer.class) (2 args for 1 param).

Common situations: Forgetting Map has two parameters; adding an extra argument after a copy-paste; confusion between Optional (1 param) and Pair-like types (2 params).

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/09fd00ac48614f25. Report an issue: GitHub.