Positional Argument Validators
Cobra validates non-flag command-line arguments through a PositionalArgs function: a callable that receives the command and parsed arguments, then returns either an error or nil.
This layer exists so commands can choose a precise argument policy instead of accepting every positional value indiscriminately. The built-in validators cover empty, bounded, exact, unique, and valid-name argument sets, and they can be composed when one rule is not enough.
Sources: args.go:22, args.go:42-47, args.go:69-79, args.go:107-114, args.go:127-136
Core concepts
Positional argument policy
A positional argument policy is the function stored in a command’s Args field and executed by ValidateArgs. If Args is nil, ValidateArgs calls ArbitraryArgs; otherwise it calls the configured validator.
Sources: command.go:1172-1177
Valid argument names
A command’s ValidArgs field is the list checked by OnlyValidArgs; entries may contain a tab-separated description, but only the text before the tab is treated as the accepted argument.
Sources: args.go:51-66
Validator composition
MatchAll creates one PositionalArgs validator that runs each supplied validator in order and returns the first error.
Sources: args.go:127-136
How validation is selected
The validation entry point chooses permissive behavior only when the command has no configured Args validator; otherwise it delegates to that validator. This makes ArbitraryArgs the behavior of a nil Args field, while explicit validators such as NoArgs impose stricter rules.
Evidence
- validate-argscommand.go:1172
- arbitrary-policyargs.go:82
- configured-policyargs.go:22
- argument-resultcommand.go:1172
The important distinction is between three permissiveness policies. ArbitraryArgs always returns nil, so it accepts any argument list. NoArgs rejects every non-empty list and reports the first value as an unknown command. legacyArgs is conditional: it accepts arguments for commands without subcommands, but for a root command with subcommands it rejects a non-empty argument list and may include a suggestion.
| Policy | Accepted input | Rejection condition |
|---|---|---|
ArbitraryArgs | Every argument list | Never rejects |
NoArgs | Only an empty list | At least one argument |
legacyArgs | Any list when there are no subcommands | Root command with subcommands and at least one argument |
MinimumNArgs | At least n arguments | Fewer than n |
MaximumNArgs | At most n arguments | More than n |
ExactArgs | Exactly n arguments | Count differs from n |
RangeArgs | Between min and max, inclusive | Count is outside the range |
NoDuplicateArgs | Lists with unique values | Any value occurs more than once |
Sources: command.go:1172-1177, args.go:82-84, args.go:42-47, args.go:28-39, args.go:69-79, args.go:87-94, args.go:97-104, args.go:107-114, args.go:117-124
How the built-in validators enforce rules
Count-based validators inspect only len(args). MinimumNArgs checks the lower bound, MaximumNArgs checks the upper bound, ExactArgs requires equality, and RangeArgs checks both bounds. Each returns nil when its condition is satisfied and an error containing the expected and received counts otherwise.
NoDuplicateArgs tracks each argument in a map and returns an error as soon as it encounters a value already seen. This is useful when repeated positional values would change the command’s meaning.
NoArgs is different from a generic count error: it formats the first supplied value as an unknown command and includes the command path.
Sources: args.go:87-94, args.go:97-104, args.go:107-114, args.go:117-124, args.go:69-79, args.go:42-47
How validators are combined
Use MatchAll when a command needs independent rules over the same argument list. It receives one or more PositionalArgs values, invokes them in order, stops at the first error, and returns nil only if all validators succeed.
Evidence
- match-allargs.go:127
- positional-validatorargs.go:22
- validation-errorargs.go:127
A common composition is exactness plus membership. ExactValidArgs is defined as MatchAll(ExactArgs(n), OnlyValidArgs), so it requires exactly n arguments and then checks that each supplied value is valid.
The order matters because MatchAll runs validators in the order supplied. With ExactValidArgs, the count rule runs before the valid-name rule; with a custom MatchAll ordering, the first failing policy determines the returned error.
Sources: args.go:127-136, args.go:142-144
How OnlyValidArgs uses ValidArgs
OnlyValidArgs performs membership validation only when cmd.ValidArgs is non-empty. It first removes descriptions by splitting each entry at the first tab, then checks every supplied argument against the resulting names.
If an argument is absent from that cleaned list, the validator returns an error containing the invalid value, the command path, and suggestions produced by findSuggestions. If cmd.ValidArgs is empty, the validator returns nil without checking the arguments.
This validator is about execution-time acceptance, not merely completion display: the command’s ValidArgs field supplies the names against which OnlyValidArgs compares user input. Separately, Cobra’s completion path also completes ValidArgs when the field is populated, including for commands that have subcommands.
Sources: args.go:51-66, completions.go:533-535
How it connects
Argument validation is one part of the command model described in Cobra Overview. A command stores its positional policy in Args, while the command tree and command path provide the context used in validation errors.
The selection of the command and its arguments occurs within the broader execution sequence described in Command Execution Flow. ValidateArgs is the local hand-off from command execution to the configured positional policy.
ValidArgs also participates in shell completion, whose dynamic and static mechanisms are described in Dynamic Completion Engine. The same field can therefore define accepted names for OnlyValidArgs and provide completion candidates.
Sources: command.go:87-98, args.go:42-47, args.go:51-66, command.go:1172-1177, completions.go:533-535
Key takeaways
ArbitraryArgsaccepts every argument list,NoArgsaccepts none, andlegacyArgschanges behavior based on subcommands.- A nil
Argsfield makesValidateArgscallArbitraryArgs; a configured field calls itsPositionalArgsvalidator. MatchAllapplies validators in order and stops at the first error.OnlyValidArgschecks supplied values against cleaned entries fromValidArgs.ExactValidArgscombines exact count validation with valid-name validation.
Sources: args.go:28-39, args.go:42-47, args.go:82-84, command.go:1172-1177, args.go:127-136, args.go:51-66, args.go:142-144