Repository: spf13/cobra
Pull request #2023 (2023-08-31 09:25:47)

Customizable error message prefix
You can change the prefix before the error message by `SetErrPrefix()`.
It's currently `Error:`, and now it's read from `errPrefix`.
It's just like the `versionTemplate` and `SetVersionTemplate()` relationship.

Resolve: #1281

CLAassistant: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/spf13/cobra?pullRequest=2023) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/spf13/cobra?pullRequest=2023) before we can accept your contribution.<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/spf13/cobra?pullRequest=2023) it.</sub>
5ouma: May I ask you which function to run to get an error message with a prefix?
I wrote this test code, but it said just an error message without `errPrefix` on the test.
It said an error message with a prefix on CLI though.

```golang
func TestErrPrefix(t *testing.T) {
	rootCmd := &Command{
		Use: "root",
		RunE: func(cmd *Command, args []string) error {
			return errors.New("error")
		},
	}
	rootCmd.SilenceUsage = true
	rootCmd.SetErrPrefix("customized error prefix:")

	checkStringContains(t, fmt.Sprint(rootCmd.Execute()), "customized error prefix: error")
}
```

```
customized error prefix: error
--- FAIL: TestErrPrefix (0.00s)
    command_test.go:77: Expected to contain: 
         customized error prefix: error
        Got:
         error
FAIL
exit status 1
FAIL    github.com/spf13/cobra  0.139s
```

<br />

When I run `executeCommand()` with an undefined flag, it says an error message with a prefix.

```golang
func TestErrPrefix(t *testing.T) {
	rootCmd := &Command{Use: "root", Run: emptyRun}
	rootCmd.SilenceUsage = true
	rootCmd.SetErrPrefix("customized error prefix:")

	output, _ := executeCommand(rootCmd, "--flag")

	checkStringContains(t, output, "customized error prefix: unknown flag: --flag")
}
```

Patch:
diff --git a/command.go b/command.go
index e4945ab..6866f7d 100644
--- a/command.go
+++ b/command.go
@@ -181,6 +181,9 @@ type Command struct {
 	// versionTemplate is the version template defined by user.
 	versionTemplate string
 
+	// errPrefix is the error message prefix defined by user.
+	errPrefix string
+
 	// inReader is a reader defined by the user that replaces stdin
 	inReader io.Reader
 	// outWriter is a writer defined by the user that replaces stdout
@@ -346,6 +349,11 @@ func (c *Command) SetVersionTemplate(s string) {
 	c.versionTemplate = s
 }
 
+// SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix.
+func (c *Command) SetErrPrefix(s string) {
+	c.errPrefix = s
+}
+
 // SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.
 // The user should not have a cyclic dependency on commands.
 func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {
@@ -595,6 +603,18 @@ func (c *Command) VersionTemplate() string {
 `
 }
 
+// ErrPrefix return error message prefix for the command
+func (c *Command) ErrPrefix() string {
+	if c.errPrefix != "" {
+		return c.errPrefix
+	}
+
+	if c.HasParent() {
+		return c.parent.ErrPrefix()
+	}
+	return "Error:"
+}
+
 func hasNoOptDefVal(name string, fs *flag.FlagSet) bool {
 	flag := fs.Lookup(name)
 	if flag == nil {
@@ -1050,7 +1070,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
 			c = cmd
 		}
 		if !c.SilenceErrors {
-			c.PrintErrln("Error:", err.Error())
+			c.PrintErrln(c.ErrPrefix(), err.Error())
 			c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath())
 		}
 		return c, err
@@ -1079,7 +1099,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
 		// If root command has SilenceErrors flagged,
 		// all subcommands should respect it
 		if !cmd.SilenceErrors && !c.SilenceErrors {
-			c.PrintErrln("Error:", err.Error())
+			c.PrintErrln(cmd.ErrPrefix(), err.Error())
 		}
 
 		// If root command has SilenceUsage flagged,
diff --git a/site/content/user_guide.md b/site/content/user_guide.md
index 56e8e44..93daadf 100644
--- a/site/content/user_guide.md
+++ b/site/content/user_guide.md
@@ -596,6 +596,12 @@ Running an application with the '--version' flag will print the version to stdou
 the version template. The template can be customized using the
 `cmd.SetVersionTemplate(s string)` function.
 
+## Error Message Prefix
+
+Cobra prints an error message when receiving a non-nil error value.
+The default error message is `Error: <error contents>`.
+The Prefix, `Error:` can be customized using the `cmd.SetErrPrefix(s string)` function.
+
 ## PreRun and PostRun Hooks
 
 It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`.  The `Persistent*Run` functions will be inherited by children if they do not declare their own.  These functions are run in the following order:


Test patch:
diff --git a/command_test.go b/command_test.go
index b0f5e86..4afb7f7 100644
--- a/command_test.go
+++ b/command_test.go
@@ -1099,6 +1099,39 @@ func TestShorthandVersionTemplate(t *testing.T) {
 	checkStringContains(t, output, "customized version: 1.0.0")
 }
 
+func TestRootErrPrefixExecutedOnSubcommand(t *testing.T) {
+	rootCmd := &Command{Use: "root", Run: emptyRun}
+	rootCmd.SetErrPrefix("root error prefix:")
+	rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
+
+	output, err := executeCommand(rootCmd, "sub", "--unknown-flag")
+	if err == nil {
+		t.Errorf("Expected error")
+	}
+
+	checkStringContains(t, output, "root error prefix: unknown flag: --unknown-flag")
+}
+
+func TestRootAndSubErrPrefix(t *testing.T) {
+	rootCmd := &Command{Use: "root", Run: emptyRun}
+	subCmd := &Command{Use: "sub", Run: emptyRun}
+	rootCmd.AddCommand(subCmd)
+	rootCmd.SetErrPrefix("root error prefix:")
+	subCmd.SetErrPrefix("sub error prefix:")
+
+	if output, err := executeCommand(rootCmd, "--unknown-root-flag"); err == nil {
+		t.Errorf("Expected error")
+	} else {
+		checkStringContains(t, output, "root error prefix: unknown flag: --unknown-root-flag")
+	}
+
+	if output, err := executeCommand(rootCmd, "sub", "--unknown-sub-flag"); err == nil {
+		t.Errorf("Expected error")
+	} else {
+		checkStringContains(t, output, "sub error prefix: unknown flag: --unknown-sub-flag")
+	}
+}
+
 func TestVersionFlagExecutedOnSubcommand(t *testing.T) {
 	rootCmd := &Command{Use: "root", Version: "1.0.0"}
 	rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})