apple/pkl · error · VmException

duplicateTypeParameter

duplicateTypeParameter

Error message

duplicateTypeParameter

What it means

Thrown when the same type parameter name appears twice in one type parameter list. Each type parameter in a list must be unique because it is stored by name and index (`new TypeParameter(variance, name, i)`).

Source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java:2321

    var params = ctx.getParameters();
    var size = params.size();
    var result = new ArrayList<TypeParameter>(size);
    for (var i = 0; i < size; i++) {
      var paramCtx = params.get(i);
      Variance variance;
      var nodeVariance = paramCtx.getVariance();
      if (nodeVariance == null) {
        variance = TypeParameter.Variance.INVARIANT;
      } else {
        variance =
            switch (nodeVariance) {
              case IN -> TypeParameter.Variance.CONTRAVARIANT;
              case OUT -> TypeParameter.Variance.COVARIANT;
            };
      }
      var parameterName = paramCtx.getIdentifier().getValue();
      if (result.stream().anyMatch(it -> it.getName().equals(parameterName))) {
        throw exceptionBuilder()
            .evalError("duplicateTypeParameter", parameterName)
            .withSourceSection(createSourceSection(paramCtx))
            .build();
      }
      result.add(new TypeParameter(variance, parameterName, i));
    }
    return result;
  }

  @Override
  public @Nullable UnresolvedTypeNode visitTypeAnnotation(@Nullable TypeAnnotation typeAnnotation) {
    return typeAnnotation == null ? null : visitType(typeAnnotation.getType());
  }

  @Override
  public Pair<ExpressionNode[], Boolean> visitArgumentList(ArgumentList argumentList) {
    var args = argumentList.getArguments();
    var res = new ExpressionNode[args.size()];

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Rename the duplicate parameter to a distinct name, e.g. `typealias Foo<T, U> = ...`.
  2. Remove the redundant parameter if it is unused or identical in intent.

Example fix

// before
typealias MapLike<K, V, K> = Mapping<K, V>
// after
typealias MapLike<K, V> = Mapping<K, V>
Defensive patterns

Strategy: validation

Validate before calling

function hasDuplicateTypeParams(names) {
  return new Set(names).size !== names.length;
}
if (hasDuplicateTypeParams(['K','V','K'])) throw new Error('duplicate type parameter name');

Prevention

When it happens

Trigger: Declaring `typealias Foo<T, T> = ...` or `typealias M<K, V, K> = ...`; the duplicate is detected by scanning the already-collected `result` list for a matching name.

Common situations: Copy-pasting type parameters and forgetting to rename; long lists like `<K, V, K>` where a collision slips in; merging two aliases by hand.

Related errors


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