netbirdio/netbird · warning

user groups cannot be empty

Error message

user groups cannot be empty

What it means

--with-user-groups was explicitly set but resolved to an empty list: cmd.Flags().Changed("with-user-groups") is true while len(exposeUserGroups) == 0. The flag is a StringSlice, and an explicitly empty string parses into zero entries, so this catches `--with-user-groups=` and `--with-user-groups ""`.

Source

Thrown at client/cmd/expose.go:131

	if isClusterProtocol(exposeProtocol) {
		if exposePin != "" || exposePassword != "" || len(exposeUserGroups) > 0 {
			return 0, fmt.Errorf("auth flags (--with-pin, --with-password, --with-user-groups) are not supported for %s protocol", exposeProtocol)
		}
	} else if cmd.Flags().Changed("with-external-port") {
		return 0, fmt.Errorf("--with-external-port is not supported for %s protocol", exposeProtocol)
	}

	if exposePin != "" && !pinRegexp.MatchString(exposePin) {
		return 0, fmt.Errorf("invalid pin: must be exactly 6 digits")
	}

	if cmd.Flags().Changed("with-password") && exposePassword == "" {
		return 0, fmt.Errorf("password cannot be empty")
	}

	if cmd.Flags().Changed("with-user-groups") && len(exposeUserGroups) == 0 {
		return 0, fmt.Errorf("user groups cannot be empty")
	}

	return port, nil
}

func isProtocolValid(exposeProtocol string) bool {
	switch strings.ToLower(exposeProtocol) {
	case "http", "https", "tcp", "udp", "tls":
		return true
	default:
		return false
	}
}

func exposeFn(cmd *cobra.Command, args []string) error {
	SetFlagsFromEnvVars(rootCmd)

	if err := util.InitLog(logLevel, util.LogConsole); err != nil {

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Pass at least one group: `--with-user-groups devops,Backend`
  2. Build the command conditionally: only append the flag when the list is non-empty (`[ -n "$GROUPS" ] && set -- "$@" --with-user-groups "$GROUPS"`)

Example fix

# before
netbird expose --with-user-groups "$GROUPS" 8080   # GROUPS empty

# after
export GROUPS=devops,Backend
netbird expose --with-user-groups "$GROUPS" 8080
Defensive patterns

Strategy: validation

Validate before calling

if groupsFlagSet && len(groups) == 0 {
	log.Fatal("--with-user-groups was set but the list is empty; pass at least one group or drop the flag")
}

Prevention

When it happens

Trigger: `--with-user-groups=` with an empty value, typically an unset or empty groups variable expanded by a wrapper script.

Common situations: Automation passing an optional groups variable that is empty in some environments; command built by string concatenation with an empty tail.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/07fc55faacd21672. Report an issue: GitHub.