apple/pkl · error
commandOptionUnsupportedType
commandOptionUnsupportedType
Error message
commandOptionUnsupportedType
What it means
Thrown when an option's declared type is a supported generic collection (Listing, Mapping, List, Set, Map, or Pair) given WITHOUT its required type arguments. The framework needs element/key/value types to know how to convert each CLI token, so bare `List<Int>` is fine but bare `List` (or `Listing`) is rejected, with a hint about how many type arguments are needed.
Solutions
- Add the type arguments, e.g. `List<String>` or `Mapping<String, Int>`
- For Listing/Mapping, parameterize them: `Listing<String>`, `Mapping<String, String>`
- Use Pair<A, B> with both type arguments for pair-typed options
Example fix
// before @Option include: List // after @Option include: List<String>
Defensive patterns
Strategy: validation
Validate before calling
// static check: collection-typed options must be parameterized
function checkRawCollections(props: Listing<ClassProperty>): Listing<String> {
props.filter((p) -> p.type != null && p.type.isRawCollection())
.map((p) -> p.name)
} Prevention
- Never declare bare List/Set/Map/Listing/Mapping/Pair types for options — always add type arguments
- Remember arity: 1 arg for List/Set/Listing, 2 for Map/Mapping/Pair
- Run spec parsing in CI so raw collection types fail at build time
When it happens
Trigger: Declaring `@Option include: List` or `@Option headers: Mapping` — a FinalClassTypeNode for Listing/Mapping/List/Set/Map/Pair with no type arguments reaches OptionBehavior.resolve and fails the first commandOptionUnsupportedType branch.
Common situations: Using raw collection types in Pkl property declarations; older Pkl code where bare Listing was common; copy-pasted specs stripped of type args.
Related errors
- cannotRenderType
- commandArgumentsMultipleRepeated
- commandArgumentUnexpectedNonRepeatedNullableType
- commandFlagInvalidType
- commandFlagNameCollision
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/bb2d9c4ab3ff43d1.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java:597
var builder = VmMap.builder();
values.forEach(
(entry) ->
builder.add(((VmPair) entry).getFirst(), ((VmPair) entry).getSecond()));
return builder.build();
};
} else if (typeNode instanceof TypeNode.PairTypeNode pairTypeNode) {
handleEntry(pairTypeNode.getFirstTypeNode(), pairTypeNode.getSecondTypeNode(), prop);
if (all == null) all = this::allChooseLast;
if (multiple == null) multiple = false;
} else if (typeNode instanceof TypeNode.FinalClassTypeNode finalClassTypeNode
&& (finalClassTypeNode.getVmClass() == BaseModule.getListingClass()
|| finalClassTypeNode.getVmClass() == BaseModule.getMappingClass()
|| finalClassTypeNode.getVmClass() == BaseModule.getListClass()
|| finalClassTypeNode.getVmClass() == BaseModule.getSetClass()
|| finalClassTypeNode.getVmClass() == BaseModule.getMapClass()
|| finalClassTypeNode.getVmClass() == BaseModule.getPairClass())) {
// if a supported type is provided without type arguments
throw exceptionBuilder()
.withSourceSection(prop.getHeaderSection())
.evalError(
"commandOptionUnsupportedType",
prop.getName(),
"",
typeNode.getSourceSection().getCharacters())
.withHint(
finalClassTypeNode.getVmClass().getSimpleName()
+ " options must provide "
+ switch (finalClassTypeNode.getVmClass().getTypeParameterCount()) {
case 1 -> "one type argument.";
case 2 -> "two type arguments.";
default -> throw PklBugException.unreachableCode();
})
.build();
} else if (each == null && all == null) {
// if another type and no transform functions are provided, that's an error
throw exceptionBuilder()View on GitHub (pinned to f3efcbfc9b)