netbirdio/netbird · error
invalid IPv6 port forward specification: %s (expected [ipv6]
Error message
invalid IPv6 port forward specification: %s (expected [ipv6]:port:host:hostport)
What it means
Returned by parseIPv6ForwardSpec when the bracketed IPv6 host was split off successfully (a ']:' was found) but the remainder does not split into exactly three colon-separated parts — local port, remote host, remote port. The expected full grammar is [ipv6]:port:host:hostport, so remainders with 2 or 4+ parts are rejected with this format-hint message.
Source
Thrown at client/cmd/ssh.go:777
localHost := normalizeLocalHost(parts[0])
localAddr := localHost + ":" + parts[1]
remoteAddr := parts[2] + ":" + parts[3]
return localAddr, remoteAddr, nil
}
// parseIPv6ForwardSpec handles "[host]:port:host:hostport" format.
func parseIPv6ForwardSpec(spec string) (string, string, error) {
idx := strings.Index(spec, "]:")
if idx == -1 {
return "", "", fmt.Errorf("invalid IPv6 port forward specification: %s", spec)
}
ipv6Host := spec[:idx+1]
remaining := spec[idx+2:]
parts := strings.Split(remaining, ":")
if len(parts) != 3 {
return "", "", fmt.Errorf("invalid IPv6 port forward specification: %s (expected [ipv6]:port:host:hostport)", spec)
}
localAddr := ipv6Host + ":" + parts[0]
remoteAddr := parts[1] + ":" + parts[2]
return localAddr, remoteAddr, nil
}
// isUnixSocket checks if a path is a Unix socket path.
func isUnixSocket(path string) bool {
return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "./")
}
// normalizeLocalHost converts "*" to "" for binding to all interfaces (dual-stack).
func normalizeLocalHost(host string) string {
if host == "*" {
return ""
}
return hostView on GitHub (pinned to 93e97f4bf1)
Solutions
- Use exactly three parts after the bracketed host: [v6]:local_port:remote_host:remote_port, with the remote host as a name or IPv4 (e.g., [::1]:8080:10.10.0.5:80).
- Give the remote side its explicit numeric port — the IPv6 form has no shorter variant.
- If the destination must be IPv6, note the parser's limit and route via a name or an IPv4-mapped intermediate instead of a bracketed remote literal.
Example fix
# before netbird ssh -L '[::1]:8080:host' peer1 # -> invalid IPv6 port forward specification: 8080:host (expected [ipv6]:port:host:hostport) # after netbird ssh -L '[::1]:8080:host:80' peer1
Defensive patterns
Strategy: validation
Validate before calling
// after splitting off [v6]:, the remainder must be exactly port:host:port
rem := spec[idx+2:]
parts := strings.Split(rem, ":")
if len(parts) != 3 {
return fmt.Errorf("after [v6]: expected port:host:hostport, got %d parts in %q", len(parts), rem)
}
if p, _ := strconv.Atoi(parts[0]); p < 1 || p > 65535 { return fmt.Errorf("bad local port") }
if p, _ := strconv.Atoi(parts[2]); p < 1 || p > 65535 { return fmt.Errorf("bad remote port") } Type guard
func isCompleteV6Forward(s string) bool {
i := strings.Index(s, "]:")
if i == -1 {
return false
}
return len(strings.Split(s[i+2:], ":")) == 3
} Try / catch
if len(parts) != 3 {
// remainder over/under-segmented: missing remote port is the common case;
// surface the expected [ipv6]:port:host:hostport shape verbatim
} Prevention
- Memorize the fixed shape: bracketed v6 host plus exactly three more colon parts.
- Do not put an IPv6 literal on the remote side — the grammar has no slot for it; use a name or IPv4.
- Build v6 forwards from typed fields so part count is guaranteed by construction.
- Table-test your spec builder with [::1] fixtures in CI.
When it happens
Trigger: `-L [::1]:8080:host peer` (remainder `8080:host` — 2 parts, remote port missing), `-L [::1]:8080:host:80:extra peer` (4 parts), or a remainder containing another unbracketed IPv6 literal such as `[::1]:8080:2001:db8::1:80`, which splits into more than three parts and fails.
Common situations: Remembering to bracket the local v6 host but not the remote one; omitting the remote port in the IPv6 form specifically; extra segments from templating. A remote IPv6 destination cannot actually be expressed in this grammar — only the local bind side supports brackets.
Related errors
- invalid port forward specification: %s
- invalid IPv6 port forward specification: %s
- start port forwarding: %w
- local port forward %s: %w
- remote port forward %s: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/2ae9c3877b3bf130.
Report an issue: GitHub.