apple/pkl · error
commandOptionsTypeAbstractClass
commandOptionsTypeAbstractClass
Error message
commandOptionsTypeAbstractClass
What it means
getOptionsClass throws commandOptionsTypeAbstractClass when the class given as a command's `options` type is abstract. Abstract classes have no instantiable properties to parse flags from, so the CLI spec parser rejects them at the class header section.
Source
Thrown at pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java:185
// at this point we've asserted the options property exists and that it is neither amended nor
// assigned
// the only possibility here is that it has a type annotation, otherwise this wouldn't parse
throw PklBugException.unreachableCode();
}
var optionsTypeNode = optionsPropertyTypeNode.getTypeNode();
if (optionsTypeNode instanceof TypeNode.TypedTypeNode) {
return BaseModule.getTypedClass();
}
if (!(optionsTypeNode instanceof TypeNode.UserClassTypeNode node)) {
throw exceptionBuilder()
.withSourceSection(optionsTypeNode.getSourceSection())
.evalError(
"commandOptionsTypeNotClass", optionsTypeNode.getSourceSection().getCharacters())
.build();
}
var clazz = node.getVmClass();
if (clazz.isAbstract()) {
throw exceptionBuilder()
.withSourceSection(clazz.getHeaderSection())
.evalError("commandOptionsTypeAbstractClass", clazz.getQualifiedName())
.build();
}
return clazz;
}
private Iterable<CommandSpec.Option> collectOptions(VmClass optionsClass) {
CommandSpec.Argument lastRepeatedArg = null;
EconomicMap<String, CommandSpec.Option> opts = EconomicMap.create();
var clazz = optionsClass;
while (clazz != null) {
for (var prop : clazz.getDeclaredProperties()) {
var name = prop.getName().toString();
if (VmModifier.isLocalOrExternalOrAbstractOrFixedOrConst(prop.getModifiers())
|| opts.containsKey(name)) continue;
View on GitHub (pinned to f3efcbfc9b)
Solutions
- Remove `abstract` from the options class
- Create a concrete subclass of the abstract base and use that as the `options` type
- Move shared fields into the abstract base but declare concrete options classes per command
Example fix
// before
abstract class Options { verbose: Boolean }
options: Options
// after
class Options extends BaseOptions { ... }
options: Options Defensive patterns
Strategy: type-guard
Validate before calling
// ensure the options class is instantiable
// abstract class Options { ... } <-- invalid
// class Options extends BaseOpts { ... } <-- valid Type guard
function isConcreteClass(c) { return c && !c.isAbstract; } Prevention
- Keep options classes concrete; put shared fields in an abstract base
- Search for `abstract class` before assigning an options type
- Make one concrete subclass per command
When it happens
Trigger: Declaring `abstract class Options { ... }` and using it as the `options` type of a CLI command.
Common situations: Factoring shared options into an abstract base class and forgetting to make the concrete per-command options class; converting an options class to abstract during refactoring.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- +e.getMessage()
- commandSubcommandConflict
- commandOptionsTypeNotClass
- commandOptionBothFlagAndArgument
- commandArgumentsMultipleRepeated
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/c255b50d0ed5f19b.
Report an issue: GitHub.