-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide usefull errors when using invalid sub command #1716
base: main
Are you sure you want to change the base?
Conversation
Hello @marckhouzam :) Sorry for the ping, just raising visibility. Is there any chance for anyone to review this change? Pretty please? :) The code is concise and contains a small, but effective fix for a relative obscure behaviour but leaves a really nice error for the user. |
Thanks @mandelsoft. To make the review easier, could you provide a simple test program and the steps to reproduce the problem? Ideally you would open an issue with that information and refer this PR to that issue. Thank you. |
Thank you, Marc! |
Hello @marckhouzam, sorry, for the delay. I could open an issue, also, if you want. The problem can be reproduced with the following program: package main
import (
"fmt"
"github.com/spf13/cobra"
)
var opt string
func main() {
cmd := &cobra.Command{
Use: "test",
Short: "test program",
Version: "v1",
TraverseChildren: true,
SilenceUsage: true,
DisableFlagsInUseLine: true,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return nil
},
}
sub := &cobra.Command{
Use: "sub",
Short: "sub command",
TraverseChildren: true,
SilenceUsage: true,
DisableFlagsInUseLine: true,
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Printf("option is %q\n", opt)
return nil
},
}
flagset := sub.Flags()
flagset.StringVarP(&opt, "opt", "", "", "some option")
cmd.AddCommand(sub)
cmd.InitDefaultHelpCmd()
cmd.Execute()
} It uses a sub command
It prints the option value. If called with a misspelled sub command
It provides the following error message:
This is not directly wrong, but misleading, the problem is not the option, but the misspelled sub command and the main command does not provide a runner (meaning it cannot be executed without a sub command). With the provided fix, the error output correctly is
|
@marckhouzam Hello. :) 👋 Are you happy with the added information? :) Thanks! 🙏 |
@marckhouzam Hello. :) 👋 Are you happy with the added information? :) Thanks! 🙏 |
If the TraverseChildren mode is active, the Traverse function returns the last accepted command along the requested sub command chain. This command is then used to parse the arguments. This will for sure fail, if the traversing was aborted because an invalid sub command was given. As a result, cobra complains about invalid flags instead of an invalid sub command.
This behaviour might be useful, if the intermediate command is Runnable(), but it for sure makes no sense, if it isn't.
This PR fixes this by providing a legacyArgs() error in case of not runnable intermediate commands.
Remark: It solves the obvious problematic behaviour, but basically the general scenario is more complex.
If the intermediate command is Runnable() in addition to providing additional sub commands, then it should be possible to forward the control about the error message to the command to be a able to distinguish between these two cases according to its needs. This is basically already possible by declaring a FlagErrorFunc(). But unfortunately it only gets the command and error as arguments, but not the actual set of arguments. Therefore it has no chance to detect the actual problem and provide appropriate error feedback.
Solving this is more invasive, because it would require, either to change the interface, or add another more general error handler option.