apple/pkl · error

commandArgumentUnexpectedNonRepeatedNullableType

commandArgumentUnexpectedNonRepeatedNullableType

Error message

commandArgumentUnexpectedNonRepeatedNullableType

What it means

Thrown when an optional CLI argument (no required flag, no default) is neither repeated nor nullable. An argument that can be omitted needs either a List/repeated shape or a `String?`-style nullable type so the command framework can represent 'not provided'; otherwise the spec is ambiguous and rejected.

Solutions

  1. Add `multiple = true` so the argument is collected as a list
  2. Change the type to nullable (e.g. `String?`) to represent omission
  3. Keep the argument required and remove `optional = true`

Example fix

// before
@Argument { optional = true } target: String

// after
@Argument { optional = true } target: String?
Defensive patterns

Strategy: validation

Validate before calling

// every optional argument must be repeated or nullable
for (arg in spec.arguments) {
  if (arg.optional && !arg.multiple && !arg.nullable)
    throw "@Argument \(arg.name): optional single arguments must be nullable or repeated"
}

Type guard

function isValidOptionalArg(optional: Boolean, multiple: Boolean, nullable: Boolean): Boolean =
  !optional || multiple || nullable

Prevention

When it happens

Trigger: Declaring `@Argument { optional = true } name: String` — optional but single-valued, non-nullable — which fails the `isOptional && !multiple` check in collectArgument.

Common situations: Marking a single positional argument optional without deciding how 'absent' is represented; loosening a required argument to optional during a refactor.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java:372

          .build();
    }

    return new CountedFlag(
        name,
        VmUtils.exportDocComment(prop.getDocComment()),
        shortName,
        (Boolean) VmUtils.readMember(flagAnnotation, Identifier.HIDE));
  }

  private Argument collectArgument(ClassProperty prop, VmTyped argAnnotation) {
    var behavior = new OptionBehavior(argAnnotation, false).resolve(prop, true);
    if (behavior.getDefaultValue() != null) {
      throw exceptionBuilder()
          .withSourceSection(prop.getHeaderSection())
          .evalError("commandOptionUnexpectedDefaultValue", prop.getName(), "Argument")
          .build();
    } else if (behavior.isOptional() && !behavior.getMultiple()) {
      throw exceptionBuilder()
          .withSourceSection(prop.getHeaderSection())
          .evalError("commandArgumentUnexpectedNonRepeatedNullableType", prop.getName())
          .build();
    }

    return new CommandSpec.Argument(
        prop.getName().toString(),
        VmUtils.exportDocComment(prop.getDocComment()),
        behavior.getEach(),
        behavior.getAll(),
        behavior.getCompletionCandidates(),
        behavior.getMultiple());
  }

  /** Unwrap nullables, constraints, and aliases and return Pair(underlying type, is nullable) */
  private Pair<TypeNode, Boolean> resolveType(ClassProperty prop) {
    var propertyTypeNode = prop.getTypeNode();
    if (propertyTypeNode != null) {

View on GitHub (pinned to f3efcbfc9b)