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
- Fix the ProxyCommand line to pass both tokens: ProxyCommand netbird ssh-proxy %h %p
- Ensure the port argument is a plain decimal number (e.g. 22, 2222), not a service name
- Check for stray whitespace/CR in the generated command by running ssh with -vvv and inspecting the executed ProxyCommand
- 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
- Always use %h %p tokens in ProxyCommand; never hardcode or omit the port
- Validate generated commands in scripts before exec: numeric host-independant port check
- Avoid service names; resolve them to numbers first
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
- start port forwarding: %w
- local port forward %s: %w
- remote port forward %s: %w
- invalid remote address: %w
- invalid local address: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/5505a49893793a63.
Report an issue: GitHub.