{"record":{"id":"16827742785fd943","repo":"apple/pkl","slug":"commandargumentunexpectednonrepeatednullabletype","errorCode":"commandArgumentUnexpectedNonRepeatedNullableType","errorMessage":"commandArgumentUnexpectedNonRepeatedNullableType","messagePattern":"commandArgumentUnexpectedNonRepeatedNullableType","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java","lineNumber":372,"sourceCode":"          .build();\n    }\n\n    return new CountedFlag(\n        name,\n        VmUtils.exportDocComment(prop.getDocComment()),\n        shortName,\n        (Boolean) VmUtils.readMember(flagAnnotation, Identifier.HIDE));\n  }\n\n  private Argument collectArgument(ClassProperty prop, VmTyped argAnnotation) {\n    var behavior = new OptionBehavior(argAnnotation, false).resolve(prop, true);\n    if (behavior.getDefaultValue() != null) {\n      throw exceptionBuilder()\n          .withSourceSection(prop.getHeaderSection())\n          .evalError(\"commandOptionUnexpectedDefaultValue\", prop.getName(), \"Argument\")\n          .build();\n    } else if (behavior.isOptional() && !behavior.getMultiple()) {\n      throw exceptionBuilder()\n          .withSourceSection(prop.getHeaderSection())\n          .evalError(\"commandArgumentUnexpectedNonRepeatedNullableType\", prop.getName())\n          .build();\n    }\n\n    return new CommandSpec.Argument(\n        prop.getName().toString(),\n        VmUtils.exportDocComment(prop.getDocComment()),\n        behavior.getEach(),\n        behavior.getAll(),\n        behavior.getCompletionCandidates(),\n        behavior.getMultiple());\n  }\n\n  /** Unwrap nullables, constraints, and aliases and return Pair(underlying type, is nullable) */\n  private Pair<TypeNode, Boolean> resolveType(ClassProperty prop) {\n    var propertyTypeNode = prop.getTypeNode();\n    if (propertyTypeNode != null) {","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java#L354-L390","documentation":"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.","triggerScenarios":"Declaring `@Argument { optional = true } name: String` — optional but single-valued, non-nullable — which fails the `isOptional && !multiple` check in collectArgument.","commonSituations":"Marking a single positional argument optional without deciding how 'absent' is represented; loosening a required argument to optional during a refactor.","solutions":["Add `multiple = true` so the argument is collected as a list","Change the type to nullable (e.g. `String?`) to represent omission","Keep the argument required and remove `optional = true`"],"exampleFix":"// before\n@Argument { optional = true } target: String\n\n// after\n@Argument { optional = true } target: String?","handlingStrategy":"validation","validationCode":"// every optional argument must be repeated or nullable\nfor (arg in spec.arguments) {\n  if (arg.optional && !arg.multiple && !arg.nullable)\n    throw \"@Argument \\(arg.name): optional single arguments must be nullable or repeated\"\n}","typeGuard":"function isValidOptionalArg(optional: Boolean, multiple: Boolean, nullable: Boolean): Boolean =\n  !optional || multiple || nullable","tryCatchPattern":null,"preventionTips":["Decide how omission is represented when making an argument optional: List or nullable type","Prefer keeping positional arguments required and moving optionality to options"],"tags":["pkl","cli","argument","nullability"],"backgroundTag":"invalid-argument-value","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}