fatedier/frp · error

nat_hole_stun_server can not be empty

Error message

nat_hole_stun_server can not be empty

What it means

The `frpc nathole` discovery command refused to run because natHoleSTUNServer is empty in the client common config. NAT-hole discovery fundamentally needs a STUN server to learn external addresses and NAT behavior, so the command fails fast before any network activity.

Source

Thrown at cmd/frpc/sub/nathole.go:97

		natFeature, err := nathole.ClassifyNATFeature(addrs, localIPs)
		if err != nil {
			fmt.Println("classify nat feature error:", err)
			os.Exit(1)
		}
		fmt.Println("STUN server:", cfg.NatHoleSTUNServer)
		fmt.Println("Your NAT type is:", natFeature.NatType)
		fmt.Println("Behavior is:", natFeature.Behavior)
		fmt.Println("External address is:", addrs)
		fmt.Println("Local address is:", localAddr.String())
		fmt.Println("Public Network:", natFeature.PublicNetwork)
		return nil
	},
}

func validateForNatHoleDiscovery(cfg *v1.ClientCommonConfig) error {
	if cfg.NatHoleSTUNServer == "" {
		return fmt.Errorf("nat_hole_stun_server can not be empty")
	}
	return nil
}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Set natHoleSTUNServer in the common config, e.g. 'stun.easyvoip.com:3478' or another reachable STUN endpoint.
  2. If it should already be set, verify the config file actually loads without parse errors and the key sits where your frp version expects it.
  3. Pass a config file to the nathole command; running without cfgFile leaves everything default.

Example fix

# before (frpc.toml)
[common]
serverAddr = "x"

# after
[common]
serverAddr = "x"
natHoleSTUNServer = "stun.easyvoip.com:3478"
Defensive patterns

Strategy: validation

Validate before calling

if cfg.NatHoleSTUNServer == "" {
    return fmt.Errorf("set natHoleSTUNServer before nathole discovery")
}

Prevention

When it happens

Trigger: Running `frpc nathole discover` (or the nathole command with only a cfgFile arg) while the loaded ClientCommonConfig has no natHoleSTUNServer set and no default applies.

Common situations: Config file omits natHoleSTUNServer and the user expected a default; a minimal or custom TOML/YAML that skipped the common section; older configs where the field was named differently during migration to the v1 schema.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/2feb461970a9cdd9. Report an issue: GitHub.