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
- Pass at least one group: `--with-user-groups devops,Backend`
- 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
- Build the command conditionally: append --with-user-groups only when the list is non-empty
- StringSlice flags parse an explicit empty string as zero entries — unset and empty are different failure modes
- Echo the variable before using it when debugging wrapper scripts
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
- password cannot be empty
- invalid port number: %s
- invalid port number: must be between 1 and 65535
- unsupported protocol %q: must be http, https, tcp, udp, or t
- auth flags (--with-pin, --with-password, --with-user-groups)
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/07fc55faacd21672.
Report an issue: GitHub.