netbirdio/netbird · error
parse address %s: %w
Error message
parse address %s: %w
What it means
Produced inside validateDestinationPort when net.SplitHostPort cannot split the destination address into host and port. SplitHostPort errors on a missing port (`address host: missing port in address`), on too many colons for an unbracketed IPv6 literal (`too many colons in address`), and on malformed bracket forms. Addresses starting with / or ./ are exempted (unix sockets) before this check.
Source
Thrown at client/cmd/ssh.go:684
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, "./") {
return nil
}
_, portStr, err := net.SplitHostPort(addr)
if err != nil {
return fmt.Errorf("parse address %s: %w", addr, err)
}
port, err := strconv.Atoi(portStr)
if err != nil {
return fmt.Errorf("invalid port %s: %w", portStr, err)
}
if port == 0 {
return fmt.Errorf("port 0 is not valid for destination address")
}
if port < 0 || port > 65535 {
return fmt.Errorf("port %d out of range (1-65535)", port)
}
return nil
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Add the :port suffix so the destination is host:port, e.g., dbhost:5432.
- Bracket IPv6 hosts before appending the port: [2001:db8::1]:443.
- If the destination is a unix socket, give it a / or ./ prefix so it bypasses this check.
- For empty ports from variables, default them explicitly: ${PORT:-80}.
Example fix
# before netbird ssh -L 8080:2001:db8::1 peer1 # -> invalid remote address: parse address 2001:db8::1: address 2001:db8::1: too many colons in address # after netbird ssh -L 8080:'[2001:db8::1]:443' peer1
Defensive patterns
Strategy: validation
Validate before calling
// pre-split before composing/running the CLI
host, portStr, err := net.SplitHostPort(candidate)
if err != nil {
if strings.Contains(err.Error(), "too many colons") {
// unbracketed IPv6: re-emit as [v6]:port
candidate = fmt.Sprintf("[%s]:%s", host, portStr) // adjust per your data shape
} else {
return fmt.Errorf("add :port to destination %q", candidate)
}
} Type guard
// true when the string is a parseable host:port or a unix socket path
func isHostPortOrSocket(s string) bool {
if strings.HasPrefix(s, "/") || strings.HasPrefix(s, "./") {
return true
}
_, _, err := net.SplitHostPort(s)
return err == nil
} Try / catch
if _, _, err := net.SplitHostPort(addr); err != nil {
// err is *net.AddrError with Err in {"missing port in address", "too many colons in address"};
// branch on it: prompt for a port vs demand brackets
} Prevention
- Always bracket IPv6 literals in any host:port string you build: [2001:db8::1]:443.
- Never emit a destination without a port; make the port a required typed field upstream of string building.
- Reuse net.SplitHostPort in your validators instead of manual strings.LastIndex logic — same semantics as the CLI.
- Unit-test spec builders with IPv6 fixtures; they are the canonical source of 'too many colons'.
When it happens
Trigger: Destination like `dbhost` (no port at all), `::1:8080` (unbracketed IPv6 plus port — SplitHostPort cannot disambiguate), `[fe80::1]` without a port, or a stray bracket form like `[host:80`. Reached from -L via `invalid remote address: ...` and from -R via `invalid local address: ...`.
Common situations: Omitting the port when shortening specs; pasting IPv6 addresses without brackets; specs assembled by string concatenation where the port segment came out empty; targets meant to be sockets but missing the leading slash so they parse as hostnames.
Related errors
- invalid port forward specification: %s
- invalid IPv6 port forward specification: %s
- invalid IPv6 port forward specification: %s (expected [ipv6]
- dial %s: %w
- start port forwarding: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/160e683872f35d96.
Report an issue: GitHub.