spf13/cobra · error

RegisterFlagCompletionFunc: flag '%s' already registered

Error message

RegisterFlagCompletionFunc: flag '%s' already registered

What it means

Returned by Command.RegisterFlagCompletionFunc when a completion function has already been registered for that exact flag. The check uses the *flag.Flag pointer as the key in the global flagCompletionFunctions map, so it is per-flag-instance, not per-name.

Source

Thrown at completions.go:179

	return func(cmd *Command, args []string, toComplete string) ([]Completion, ShellCompDirective) {
		return choices, directive
	}
}

// RegisterFlagCompletionFunc should be called to register a function to provide completion for a flag.
//
// You can use pre-defined completion functions such as [FixedCompletions] or [NoFileCompletions],
// or you can define your own.
func (c *Command) RegisterFlagCompletionFunc(flagName string, f CompletionFunc) error {
	flag := c.Flag(flagName)
	if flag == nil {
		return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName)
	}
	flagCompletionMutex.Lock()
	defer flagCompletionMutex.Unlock()

	if _, exists := flagCompletionFunctions[flag]; exists {
		return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' already registered", flagName)
	}
	flagCompletionFunctions[flag] = f
	return nil
}

// GetFlagCompletionFunc returns the completion function for the given flag of the command, if available.
func (c *Command) GetFlagCompletionFunc(flagName string) (CompletionFunc, bool) {
	flag := c.Flag(flagName)
	if flag == nil {
		return nil, false
	}

	flagCompletionMutex.RLock()
	defer flagCompletionMutex.RUnlock()

	completionFunc, exists := flagCompletionFunctions[flag]
	return completionFunc, exists
}

View on GitHub (pinned to adbc881390)

Solutions

  1. Register each flag's completion exactly once; move registration to a single setup function.
  2. In tests, build a fresh command tree and avoid process-global double registration (the map is package-global).
  3. Check the returned error and ignore/skip on already-registered if duplicate registration is benign in your flow.
  4. Use GetFlagCompletionFunc to check existence before registering.

Example fix

// before: helper called twice registers twice
setupCmd(cmd)
setupCmd(cmd) // error: already registered

// after: register once, or guard
if _, ok := cmd.GetFlagCompletionFunc("output"); !ok {
    cmd.RegisterFlagCompletionFunc("output", fn)
}
Defensive patterns

Strategy: validation

Validate before calling

// Idempotent registration helper
func registerCompletionOnce(cmd *cobra.Command, name string, fn cobra.CompletionFunc) error {
    if _, ok := cmd.GetFlagCompletionFunc(name); ok {
        return nil // already registered
    }
    return cmd.RegisterFlagCompletionFunc(name, fn)
}

Type guard

null

Try / catch

if err := cmd.RegisterFlagCompletionFunc(name, fn); err != nil {
    if strings.Contains(err.Error(), "already registered") { return nil }
    return err
}

Prevention

When it happens

Trigger: Calling RegisterFlagCompletionFunc twice for the same flag in the same process — common when setup code runs in an init() that executes multiple times (e.g. tests re-instantiating commands, or a command struct reused across runs).

Common situations: Test suites that rebuild the command tree per test without resetting state, shared helper that registers completion being called twice, or a subcommand whose completion was registered both at parent and child level.

Related errors


AI-assisted analysis of spf13/cobra@adbc881390 (2026-08-04). Data as JSON: /data/errors/163835648b3387f5.json. Report an issue: GitHub.