{"record":{"id":"0a10c3b1fcb07887","repo":"apple/pkl","slug":"commandsubcommandconflict","errorCode":"commandSubcommandConflict","errorMessage":"commandSubcommandConflict","messagePattern":"commandSubcommandConflict","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java","lineNumber":141,"sourceCode":"                    // NB: these next two lines are the only place where we lose type safety.\n                    // SubcommandState is type-erased to Object in the public API to hide internals.\n                    // Consumers of this API must ensure CommandSpec.apply is only ever passed an\n                    // instance of CommandSpec.State previously returned from a prior invocation\n                    // of CommandSpec.apply.\n                    parent == null ? null : (SubcommandState) parent.contents()),\n                (it) -> handleErrors(() -> evaluateResult(command, (SubcommandState) it))));\n  }\n\n  private List<CommandSpec> collectSubcommands(VmTyped commandInfo) {\n    var subcommands = new ArrayList<CommandSpec>();\n    var subcommandNames = new HashSet<String>();\n    var subcommandsProperty = (VmObject) VmUtils.readMember(commandInfo, Identifier.SUBCOMMANDS);\n    subcommandsProperty.force(false, false);\n    subcommandsProperty.iterateAlreadyForcedMemberValues(\n        (key, member, value) -> {\n          var spec = parse((VmTyped) value);\n          if (subcommandNames.contains(spec.name())) {\n            throw exceptionBuilder()\n                .withSourceSection(member.getSourceSection())\n                .evalError(\n                    \"commandSubcommandConflict\",\n                    VmUtils.readMember(commandInfo, Identifier.NAME),\n                    spec.name())\n                .build();\n          }\n          subcommandNames.add(spec.name());\n          subcommands.add(spec);\n          return true;\n        });\n\n    return subcommands;\n  }\n\n  // region options handling\n\n  private VmClass getOptionsClass(VmTyped command) {","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java#L123-L159","documentation":"CommandSpecParser.collectSubcommands throws commandSubcommandConflict when two subcommands declared in a Pkl CLI command's `subcommands` mapping have the same name. parse() builds the parent spec, and the duplicate member's source section is used for the error. The CLI cannot dispatch ambiguously, so the spec is rejected at build time.","triggerScenarios":"Declaring `subcommands { [\"deploy\"] { ... }; [\"deploy\"] { ... } }` — two members whose parsed CommandSpec.name() collides within one command's subcommands object.","commonSituations":"Copy-pasting a subcommand block and forgetting to rename it; generating subcommands programmatically from a list with duplicate keys/names.","solutions":["Rename one of the conflicting subcommands so names are unique within the command","Remove the duplicated subcommand block","If generating subcommands from data, deduplicate names before emitting the Pkl source"],"exampleFix":"// before\nsubcommands {\n  [\"build\"] { ... }\n  [\"build\"] { ... }\n}\n// after\nsubcommands {\n  [\"build\"] { ... }\n  [\"test\"] { ... }\n}","handlingStrategy":"validation","validationCode":"const names = Object.keys(subcommandsSpec);\nconst dupes = names.filter((n, i) => names.indexOf(n) !== i);\nif (dupes.length) throw new Error(`duplicate subcommand names: ${dupes}`);","typeGuard":null,"tryCatchPattern":"try { parseCommandSpec(pklSource) } catch (e) {\n  if (String(e).includes(\"commandSubcommandConflict\")) { /* fix duplicate name in pkl */ }\n}","preventionTips":["Deduplicate generated subcommand names before emitting Pkl","Review pasted subcommand blocks for leftover duplicates","Give each subcommand a unique, action-specific name"],"tags":["pkl","cli","command-spec","naming"],"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-14T11:17:12.474Z"}