netbirdio/netbird · error
invalid local address: %w
Error message
invalid local address: %w
What it means
Wraps validateDestinationPort(localAddr) in the -R (remote forward) path. For remote forwards the spec is parsed as remoteAddr:localAddr and the validator is applied to the local address — the endpoint your machine will serve to the remote peer. It must be host:numeric-port (1-65535) or a unix socket path (leading / or ./).
Source
Thrown at client/cmd/ssh.go:660
go func() {
if err := c.LocalPortForward(ctx, localAddr, remoteAddr); err != nil && !errors.Is(err, context.Canceled) {
cmd.Printf("Local port forward error: %v\n", err)
}
}()
return nil
}
// parseAndStartRemoteForward parses and starts a remote port forward (-R)
func parseAndStartRemoteForward(ctx context.Context, c *sshclient.Client, forward string, cmd *cobra.Command) error {
remoteAddr, localAddr, err := parsePortForwardSpec(forward)
if err != nil {
return err
}
if err := validateDestinationPort(localAddr); err != nil {
return fmt.Errorf("invalid local address: %w", err)
}
log.Debugf("Remote port forwarding: %s -> %s", remoteAddr, localAddr)
go func() {
if err := c.RemotePortForward(ctx, remoteAddr, localAddr); err != nil && !errors.Is(err, context.Canceled) {
cmd.Printf("Remote port forward error: %v\n", err)
}
}()
return nil
}
// validateDestinationPort checks that the destination address has a valid port.
// Port 0 is only valid for bind addresses (where the OS picks an available port),
// not for destination addresses where we need to connect.
func validateDestinationPort(addr string) error {
if strings.HasPrefix(addr, "/") || strings.HasPrefix(addr, "./") {View on GitHub (pinned to 93e97f4bf1)
Solutions
- Complete the spec with the local service's host and numeric port: -R 9000:127.0.0.1:8080.
- Never use 0 for the local port — the remote peer dials a concrete endpoint.
- Use only digits for the local port (no service names), 1-65535.
- For unix socket targets, keep the absolute or ./-prefixed path so validation skips the port checks.
Example fix
# before netbird ssh -R 9000:localhost peer1 # -> start port forwarding: remote port forward 9000:localhost: invalid local address: parse address localhost: missing port in address # after netbird ssh -R 9000:127.0.0.1:8080 peer1
Defensive patterns
Strategy: validation
Validate before calling
// pre-check the -R local endpoint (what the remote peer dials back to)
func validateLocalTarget(addr string) error {
if strings.HasPrefix(addr, "/") || strings.HasPrefix(addr, "./") {
return nil
}
host, portStr, err := net.SplitHostPort(addr)
if err != nil {
return fmt.Errorf("local endpoint %q must be host:port", addr)
}
_ = host
p, err := strconv.Atoi(portStr)
if err != nil || p < 1 || p > 65535 {
return fmt.Errorf("local port %q invalid (need 1-65535)", portStr)
}
return nil
} Try / catch
if err := validateDestinationPort(localAddr); err != nil {
return fmt.Errorf("invalid local address: %w", err)
// the validated side is the LOCAL endpoint even though the flag is -R;
// read the wrapped cause to see if it is shape (SplitHostPort) or value (port)
} Prevention
- Document in team runbooks: -R spec ends with the local host:port pair, fully explicit.
- Reject empty/zero ports at config parse time in your own tooling (${LOCAL_PORT:?required}).
- Prefer 127.0.0.1 over localhost for the local endpoint to avoid resolver surprises on exotic hosts.
- Keep socket paths absolute so they take the exemption path instead of being parsed as host:port.
When it happens
Trigger: `netbird ssh -R 9000:localhost peer` (local side missing its port), `-R 9000:localhost:0`, `-R 9000:localhost:99999`, `-R 9000:svc:https` (non-numeric), or a local endpoint that fails net.SplitHostPort such as a bare unbracketed IPv6 address.
Common situations: Thinking -R ends at the remote bind port and omitting the local service port; environment-variable-built specs with an empty local port; pointing the local side at a socket but forgetting the leading / (so it is treated as a host with a bad port).
Related errors
- start port forwarding: %w
- local port forward %s: %w
- remote port forward %s: %w
- invalid remote address: %w
- invalid port forward specification: %s (expected format: [lo
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/eeb55c6879c6cb15.
Report an issue: GitHub.