Currently I'm trying to debug this situation and I'm really struggling to find the issue due to the lack of meaningful error message. Specifically:
import (
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// sendCmd represents the send command
var sendCmd = &cobra.Command{
Use: "send",
Short: "",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Cycling through keys")
fmt.Println(viper.AllKeys())
for _, key := range viper.AllKeys() {
fmt.Println(viper.Get(key))
}
},
}
func init() {
RootCmd.AddCommand(sendCmd)
sendCmd.PersistentFlags().StringP("identifier", "i", "", "The identifier")
viper.BindPFlag("send.identifier", sendCmd.Flags().Lookup("identifier"))
sendCmd.PersistentFlags().StringP("frequency", "f", "30s", "The frequency")
viper.BindPFlag("send.frequency", sendCmd.Flags().Lookup("frequency"))
}
When I run this though:
~/g/g/s/n/s/s/n/project ❯❯❯ sudo project send
Using config file: /Users/example/.project.json
Cycling through keys
[send.identifier send.frequency general.pidfile general send logging.verbosity logging.stdout]
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x50 pc=0xa62cc]
goroutine 1 [running]:
panic(0x645da0, 0xc8200100d0)
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/panic.go:481 +0x3ff
github.com/spf13/viper.pflagValue.HasChanged(0x0, 0xc820075500)
/Users/example/git/go/src/github.com/spf13/viper/flags.go:41 +0x3c
github.com/spf13/viper.(*Viper).find(0xc8201360e0, 0x6f2980, 0xe, 0x0, 0x0)
/Users/example/git/go/src/github.com/spf13/viper/viper.go:738 +0x19d
github.com/spf13/viper.(*Viper).Get(0xc8201360e0, 0x6f2980, 0xe, 0x0, 0x0)
/Users/example/git/go/src/github.com/spf13/viper/viper.go:461 +0x12c
github.com/spf13/viper.Get(0x6f2980, 0xe, 0x0, 0x0)
/Users/example/git/go/src/github.com/spf13/viper/viper.go:456 +0x61
repo/stash/scm/group/project/cmd.glob.func1(0x9b9760, 0x9dc260, 0x0, 0x0)
/Users/example/git/go/src/repo/stash/scm/group/project/cmd/send.go:36 +0x2f9
github.com/spf13/cobra.(*Command).execute(0x9b9760, 0x9dc260, 0x0, 0x0, 0x0, 0x0)
/Users/example/git/go/src/github.com/spf13/cobra/command.go:565 +0xb5b
github.com/spf13/cobra.(*Command).ExecuteC(0x9b9560, 0x9b9760, 0x0, 0x0)
/Users/example/git/go/src/github.com/spf13/cobra/command.go:651 +0x6bc
github.com/spf13/cobra.(*Command).Execute(0x9b9560, 0x0, 0x0)
/Users/example/git/go/src/github.com/spf13/cobra/command.go:610 +0x3b
repo/stash/scm/group/project/cmd.Execute()
/Users/example/git/go/src/repo/stash/scm/group/project/cmd/root.go:51 +0x4d
main.main()
/Users/example/git/go/src/repo/stash/scm/group/project/main.go:20 +0x26
In the root config for viper:
cobra.OnInitialize(initConfig)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags, which, if defined here,
// will be global for your application.
RootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file (default is $HOME/.surveil.yaml)")
switch runtime.GOOS {
case "windows":
wd, _ := os.Getwd()
RootCmd.PersistentFlags().StringVarP(&pidFile, "pid", "p", wd+"/surveil.pid", "absolute path to PID file")
default:
RootCmd.PersistentFlags().StringVarP(&pidFile, "pid", "p", "/var/run/surveil.pid", "absolute path to PID file")
}
pid, err := pidfile.New(pidFile)
if err != nil {
log.Fatal(err)
}
defer pid.Remove()
viper.BindPFlag("general.pidfile", RootCmd.Flags().Lookup("pid"))
RootCmd.PersistentFlags().IntVarP(&verbose, "verbosity", "v", logger.LogInfo, "set verbosity level of application to number between 0–3")
viper.BindPFlag("logging.verbosity", RootCmd.Flags().Lookup("verbosity"))
RootCmd.PersistentFlags().BoolP("stdout", "o", false, "enable logging to stdout")
viper.BindPFlag("logging.stdout", RootCmd.Flags().Lookup("stdout"))
RootCmd.PersistentFlags().BoolP("syslog", "s", false, "enable logging to syslog")
viper.BindPFlag("logging.syslog", RootCmd.Flags().Lookup("stdout"))
I've attempted to go get -u both viper and cobra. Having a more meaningful error may make this easier to debug in the future.
My configuration file:
general:
pidFile: /var/run/project.pid
send:
frequency: 30s
identifier: Example
receiverIPs: ["127.0.0.1"]
logging:
verbosity: 1 # LogInfo
stdout: true
syslog: false
send:
prefix: "[Project Forwarder]"
For @kkirsche or anyone that has the same error it is caused by you setting a PersistantFlags(), then looking up from Flags() in the next line. I just did exactly the same thing and thought it wouldn't cause an issue.
It should definitely error here saying there is no flag of that name or something.
A working example for the above would be:
RootCmd.PersistentFlags().IntVarP(&verbose, "verbosity", "v", logger.LogInfo, "set verbosity level of application to number between 0–3")
viper.BindPFlag("logging.verbosity", RootCmd.PersistentFlags().Lookup("verbosity"))
Ah, ok. Thank you for the information about why this was happening. If I have time I'll have to see if I can add that error into the package(s) if that is of interest
Most helpful comment
For @kkirsche or anyone that has the same error it is caused by you setting a
PersistantFlags(), then looking up fromFlags()in the next line. I just did exactly the same thing and thought it wouldn't cause an issue.It should definitely error here saying there is no flag of that name or something.
A working example for the above would be: