{"record":{"id":"82ca4283df153819","repo":"apple/pkl","slug":"commandoptionnotypeannotation","errorCode":"commandOptionNoTypeAnnotation","errorMessage":"commandOptionNoTypeAnnotation","messagePattern":"commandOptionNoTypeAnnotation","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java","lineNumber":393,"sourceCode":"          .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) {\n      return resolveType(propertyTypeNode.getTypeNode());\n    }\n    throw exceptionBuilder()\n        .withSourceSection(prop.getHeaderSection())\n        .evalError(\"commandOptionNoTypeAnnotation\", prop.getName())\n        .build();\n  }\n\n  /** Unwrap nullables, constraints, and aliases and return Pair(underlying type, is nullable) */\n  private Pair<TypeNode, Boolean> resolveType(TypeNode typeNode) {\n    var isNullable = false;\n    while (true) {\n      if (typeNode instanceof TypeNode.NullableTypeNode nullableTypeNode) {\n        isNullable = true;\n        typeNode = nullableTypeNode.getElementTypeNode();\n      } else if (typeNode instanceof TypeNode.ConstrainedTypeNode constrainedTypeNode) {\n        typeNode = constrainedTypeNode.getChildTypeNode();\n      } else if (typeNode instanceof TypeNode.TypeAliasTypeNode typeAliasTypeNode) {\n        if (typeAliasTypeNode.getVmTypeAlias() == BaseModule.getCharTypeAlias()) break;\n        typeNode = typeAliasTypeNode.getAliasedTypeNode();\n      } else {","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java#L375-L411","documentation":"Thrown when a CLI option, flag, or argument property has no type annotation at all (e.g. just `verbosity:`, relying on amending). The command framework derives value parsing and validation from the declared type, so a property collected as a CLI parameter must carry an explicit type annotation.","triggerScenarios":"Declaring a @Option/@Flag/@CountedFlag/@Argument property without a type, e.g. `@Option verbose:` — resolveType finds prop.getTypeNode() == null and throws.","commonSituations":"Amending-style shorthand Pkl habits carried into a command spec class; deleting a type during refactoring; relying on base-class property types without redeclaring.","solutions":["Add an explicit type annotation to the property (e.g. `verbose: Boolean`)","If inheriting from a base class, redeclare the property with its type in the command spec class","Use a supported type (String, Int, Boolean, List, Listing, Map, etc.)"],"exampleFix":"// before\n@Option verbose:\n\n// after\n@Option verbose: Boolean","handlingStrategy":"validation","validationCode":"// ensure every CLI parameter property has a type annotation before spec parse\nfor (prop in commandClass.properties) {\n  if (prop.hasAnnotation(\"Option\") && prop.type == null) throw \"missing type annotation\"\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use amendment-style untyped properties in command spec classes","Always write an explicit supported type on @Option/@Flag/@CountedFlag/@Argument properties"],"tags":["pkl","cli","missing-type-annotation"],"backgroundTag":"missing-required-config-field","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"}