spf13/viper · error

flag for %q is nil

Error message

flag for %q is nil

What it means

Returned by Viper.BindPFlag (viper.go:1107-1110) when the passed *pflag.Flag is nil. The nil almost always comes from pflag.FlagSet.Lookup(name), which returns nil for a flag that is not defined on that set.

Source

Thrown at viper.go:1109

func (v *Viper) BindPFlags(flags *pflag.FlagSet) error {
	return v.BindFlagValues(pflagValueSet{flags})
}

// BindPFlag binds a specific key to a pflag (as used by cobra).
// Example (where serverCmd is a Cobra instance):
//
//	serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
//	Viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) }

// BindPFlag binds a specific key to a pflag (as used by cobra).
// Example (where serverCmd is a Cobra instance):
//
//	serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
//	Viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error {
	if flag == nil {
		return fmt.Errorf("flag for %q is nil", key)
	}
	return v.BindFlagValue(key, pflagValue{flag})
}

// BindFlagValues binds a full FlagValue set to the configuration, using each flag's long
// name as the config key.
func BindFlagValues(flags FlagValueSet) error { return v.BindFlagValues(flags) }

// BindFlagValues binds a full FlagValue set to the configuration, using each flag's long
// name as the config key.
func (v *Viper) BindFlagValues(flags FlagValueSet) (err error) {
	flags.VisitAll(func(flag FlagValue) {
		if err = v.BindFlagValue(flag.Name(), flag); err != nil {
			return
		}
	})
	return nil
}

View on GitHub (pinned to 528f7416c4)

Solutions

  1. Nil-check the Lookup result before binding: if f := flags.Lookup("port"); f != nil { v.BindPFlag("port", f) }.
  2. Register the flag first (e.g. cmd.Flags().Int("port", 8080, "...")) before calling BindPFlag.
  3. Look up on the correct FlagSet — PersistentFlags() for inherited flags, Flags() for local.

Example fix

// before
v.BindPFlag("port", cmd.Flags().Lookup("port")) // -> flag for "port" is nil

// after
if f := cmd.Flags().Lookup("port"); f != nil {
    _ = v.BindPFlag("port", f)
} else {
    // flag not defined; register it or log the misconfiguration
}
Defensive patterns

Strategy: type-guard

Validate before calling

func bindFlag(v *viper.Viper, key string, flags *pflag.FlagSet, name string) error {
    f := flags.Lookup(name)
    if f == nil {
        return fmt.Errorf("flag %q not defined on the FlagSet", name)
    }
    return v.BindPFlag(key, f)
}

Type guard

// nil-guard for *pflag.Flag before binding
func isFlagBoundable(f *pflag.Flag) bool { return f != nil }

// usage
if f := cmd.Flags().Lookup("port"); isFlagBoundable(f) {
    _ = v.BindPFlag("port", f)
}

Try / catch

if err := v.BindPFlag("port", cmd.Flags().Lookup("port")); err != nil {
    if strings.Contains(err.Error(), "is nil") {
        // flag not registered or looked up on the wrong FlagSet
    }
}

Prevention

When it happens

Trigger: v.BindPFlag("port", cmd.Flags().Lookup("port")) where 'port' was never added to cmd.Flags(); typo in the flag name; binding before the flag is registered; looking up on the wrong FlagSet (LocalFlags vs PersistentFlags).

Common situations: Cobra app where the flag lives on PersistentFlags but Lookup is called on LocalFlags; refactor that renamed a flag but left the old string in BindPFlag; binding inside an init() that runs before flag registration.

Related errors


AI-assisted analysis of spf13/viper@528f7416c4 (2026-08-04). Data as JSON: /data/errors/21ab4f1ed30d0aac.json. Report an issue: GitHub.