Flag Groups: Required, One-Required, Mutually Exclusive
Flag groups let a command describe relationships among several flags instead of validating each flag independently. Cobra supports groups that require all participating flags together, require at least one member, or reject multiple members being set.
The relationship is recorded as flag annotations and later evaluated from each flag’s Changed state. This separates registration from validation: setup names the group, while validation decides whether the current invocation satisfies it.
Sources: flag_groups.go:33-45, flag_groups.go:49-61, flag_groups.go:65-77, flag_groups.go:81-109
Core concepts
Required-together group
A required-together group means that setting any member requires every member to be set. The public registration method is MarkFlagsRequiredTogether.
Sources: flag_groups.go:26, flag_groups.go:33-45
One-required group
A one-required group means that at least one member must be set, while setting multiple members is allowed by this group’s own validator. The public registration method is MarkFlagsOneRequired.
Sources: flag_groups.go:27, flag_groups.go:49-61, flag_groups.go:167-186
Mutually exclusive group
A mutually exclusive group means that zero or one member may be set, but two or more members are rejected. The public registration method is MarkFlagsMutuallyExclusive.
These three group kinds use distinct internal annotation keys and distinct status maps during validation.
| Group | Registration method | Internal annotation | Accepted set counts |
|---|---|---|---|
| Required together | MarkFlagsRequiredTogether | requiredAsGroupAnnotation | Zero or all |
| One required | MarkFlagsOneRequired | oneRequiredAnnotation | One or more |
| Mutually exclusive | MarkFlagsMutuallyExclusive | mutuallyExclusiveAnnotation | Zero or one |
Sources: flag_groups.go:28, flag_groups.go:65-77, flag_groups.go:188-207, flag_groups.go:26, flag_groups.go:27, flag_groups.go:81-109, flag_groups.go:33-45, flag_groups.go:49-61, flag_groups.go:144-165, flag_groups.go:167-186
How a group is registered
Each registration method first calls mergePersistentFlags, then looks up every supplied name through Flags().Lookup. If a name is missing, the method panics with a group-specific error.
For a required-together group, Cobra stores the space-joined flag list under requiredAsGroupAnnotation on every participating flag. Repeated registration appends another annotation entry, so the same flag can carry more than one group relationship.
MarkFlagsOneRequired follows the same annotation pattern using oneRequiredAnnotation. MarkFlagsMutuallyExclusive uses mutuallyExclusiveAnnotation, and its implementation explicitly allows a flag to belong to multiple groups.
This workflow shows the hand-off from public registration methods to annotations, then from annotations to validation.
Evidence
- required-registrationflag_groups.go:33
- one-registrationflag_groups.go:49
- exclusive-registrationflag_groups.go:65
- flag-annotationsflag_groups.go:33
- flag-annotationsflag_groups.go:49
- flag-annotationsflag_groups.go:65
- group-statusflag_groups.go:121
- group-validationflag_groups.go:81
- validation-errorsflag_groups.go:144
- validation-errorsflag_groups.go:167
- validation-errorsflag_groups.go:188
Sources: flag_groups.go:33-45, flag_groups.go:49-61, flag_groups.go:65-77, flag_groups.go:26, flag_groups.go:27, flag_groups.go:28, flag_groups.go:81-109, flag_groups.go:121-142, flag_groups.go:144-165, flag_groups.go:167-186, flag_groups.go:188-207
How validation distinguishes the group kinds
ValidateFlagGroups returns immediately when DisableFlagParsing is enabled. Otherwise, it obtains c.Flags(), creates one status map for each group kind, visits every flag, and processes all three annotations for each flag.
The status maps use the joined flag list as a group identifier and map each flag name to a Boolean. processFlagForGroupAnnotation initializes a group only when hasAllFlags confirms that every named flag is defined; it then records each flag’s Changed value.
After collection, validation runs in a fixed order: required-together groups, one-required groups, then mutually exclusive groups. The first returned error stops the method; otherwise, ValidateFlagGroups returns nil.
For required-together groups, an invocation is valid when none or all members are set. If only some are set, the validator sorts the missing names and returns an error shaped like: if any flags in the group [%v] are set they must all be set; missing %v.
For one-required groups, the validator collects set members and accepts the group when the count is at least one. If the count is zero, the user sees an error shaped like: at least one of the flags in the group [%v] is required.
For mutually exclusive groups, the validator accepts zero or one set member. When two or more are set, it returns an error shaped like: if any flags in the group [%v] are set none of the others can be; %v were all set.
The following call order is visible inside ValidateFlagGroups; the supplied excerpts do not show a caller from Execute or ExecuteC, so they do not establish the exact command-execution phase in which that method is invoked.
Evidence
- commandflag_groups.go:81
- annotation-processingflag_groups.go:81
- annotation-processingflag_groups.go:121
- required-checkflag_groups.go:144
- one-required-checkflag_groups.go:167
- exclusive-checkflag_groups.go:188
- resultflag_groups.go:81
- resultflag_groups.go:144
- resultflag_groups.go:167
Sources: flag_groups.go:81-109, flag_groups.go:121-142, flag_groups.go:144-165, flag_groups.go:167-186, flag_groups.go:188-207
Completion behavior
Completion uses a separate method, enforceFlagGroupsForCompletion, and also returns immediately when DisableFlagParsing is enabled. It builds the same three categories of group status and processes annotations from every flag.
When a required-together group has one flag set, completion marks the group’s flags as required through MarkFlagRequired. When a one-required group has no flag set, completion marks every member as required.
When a mutually exclusive group has one member set, completion looks up the other members and marks them hidden, while leaving the already-set flag visible. This affects suggestions; it is distinct from the validation errors returned by ValidateFlagGroups.
Sources: flag_groups.go:225-290, flag_groups.go:81-109
How it connects
Flag-group registration operates on the command’s merged flag view through mergePersistentFlags and c.Flags(), so it belongs with the repository’s broader flag layering and parsing behavior described in Flag Parsing & Persistent Flags.
The separate completion path uses parsed flag state and completion-specific required annotations, connecting group-aware suggestions to Dynamic Completion Engine.
For the broader command lifecycle, this page identifies ValidateFlagGroups as the group-validation entry point, but the supplied excerpts do not show its caller. Use Command Execution Flow for the surrounding execution sequence.
Sources: flag_groups.go:33-45, flag_groups.go:49-61, flag_groups.go:65-77, flag_groups.go:225-290, flag_groups.go:81-109
Key takeaways
- Use
MarkFlagsRequiredTogetherwhen setting one flag should require all members. - Use
MarkFlagsOneRequiredwhen at least one member must be set. - Use
MarkFlagsMutuallyExclusivewhen no more than one member may be set. ValidateFlagGroupsevaluates the three group types in required, one-required, then exclusive order.- The provided source shows the validation method and its internal order, but not its caller in command execution.