netbirdio/netbird · warning

invalid port: %s

Error message

invalid port: %s

What it means

ssh-proxy takes exactly two positional arguments, host and port, and the port is parsed with strconv.Atoi. Any non-decimal port (letters, empty string, a service name like 'ssh', or a trailing newline from shell expansion) makes Atoi fail and the command aborts with 'invalid port: <value>'.

Source

Thrown at client/cmd/ssh.go:823

}

func sshProxyFn(cmd *cobra.Command, args []string) error {
	logOutput := "console"
	if firstLogFile := util.FindFirstLogPath(logFiles); firstLogFile != "" && firstLogFile != defaultLogFile {
		logOutput = firstLogFile
	}

	proxyLogLevel := getEnvOrDefault("LOG_LEVEL", logLevel)
	if err := util.InitLog(proxyLogLevel, logOutput); err != nil {
		return fmt.Errorf("init log: %w", err)
	}

	host := args[0]
	portStr := args[1]

	port, err := strconv.Atoi(portStr)
	if err != nil {
		return fmt.Errorf("invalid port: %s", portStr)
	}

	// Check env var for browser setting since this command is invoked via SSH ProxyCommand
	// where command-line flags cannot be passed. Default is to open browser.
	noBrowser := getBoolEnvOrDefault("NO_BROWSER", false)
	var browserOpener func(string) error
	if !noBrowser {
		browserOpener = util.OpenBrowser
	}

	proxy, err := sshproxy.New(daemonAddr, host, port, cmd.ErrOrStderr(), browserOpener)
	if err != nil {
		return fmt.Errorf("create SSH proxy: %w", err)
	}
	defer func() {
		if err := proxy.Close(); err != nil {
			log.Debugf("close SSH proxy: %v", err)
		}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Fix the ProxyCommand line to pass both tokens: ProxyCommand netbird ssh-proxy %h %p
  2. Ensure the port argument is a plain decimal number (e.g. 22, 2222), not a service name
  3. Check for stray whitespace/CR in the generated command by running ssh with -vvv and inspecting the executed ProxyCommand
  4. Echo the exact command your wrapper builds and run netbird ssh-proxy host port by hand

Example fix

# before
Host mypeer
  ProxyCommand netbird ssh-proxy %h

# after
Host mypeer
  ProxyCommand netbird ssh-proxy %h %p
Defensive patterns

Strategy: validation

Validate before calling

port, err := strconv.Atoi(strings.TrimSpace(portStr))
if err != nil || port < 1 || port > 65535 {
    return fmt.Errorf("port must be a decimal 1-65535, got %q", portStr)
}

Type guard

func isValidPort(s string) bool {
    p, err := strconv.Atoi(strings.TrimSpace(s))
    return err == nil && p >= 1 && p <= 65535
}

Prevention

When it happens

Trigger: SSH ProxyCommand template that omits %p or substitutes the wrong token; passing 'ssh' instead of 22; port passed as '22\r' from a Windows/CR-terminated config; quoting that glues host and port together so args[1] is wrong.

Common situations: Hand-edited ~/.ssh/config with ProxyCommand netbird ssh-proxy %h (missing %p); automation scripts that compute the port with a command substitution returning an empty or non-numeric value.

Related errors


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