netbirdio/netbird · error
invalid IPv6 port forward specification: %s
Error message
invalid IPv6 port forward specification: %s
What it means
Returned by parseIPv6ForwardSpec when a spec that starts with '[' does not contain the closing ']:'. The parser needs that exact marker to split the bracketed IPv6 literal from the rest; without it there is no safe place to cut, so the whole spec is rejected before any port validation. This is the bare form of the message — no format hint is attached.
Source
Thrown at client/cmd/ssh.go:769
}
localAddr := "localhost:" + parts[0]
remoteAddr := parts[1] + ":" + parts[2]
return localAddr, remoteAddr, nil
}
// parseFourPartForwardSpec handles "host:port:host:hostport" format.
func parseFourPartForwardSpec(parts []string) (string, string, error) {
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, "./")View on GitHub (pinned to 93e97f4bf1)
Solutions
- Close the bracket and follow it with a colon: [2001:db8::1]:8080:host:80.
- When building specs programmatically, use fmt.Sprintf("[%s]:%s:%s:%s", v6host, lport, rhost, rport) rather than manual concatenation.
- Sanity-check the rendered spec with a regexp like ^\[[0-9a-fA-F:]+\]: before passing it to the CLI.
Example fix
# before netbird ssh -L '[::1:8080:host:80' peer1 # -> invalid IPv6 port forward specification: [::1:8080:host:80 # after netbird ssh -L '[::1]:8080:host:80' peer1
Defensive patterns
Strategy: validation
Validate before calling
if strings.HasPrefix(spec, "[") && !strings.Contains(spec, "]:") {
return fmt.Errorf("IPv6 spec %q missing ']:" + "' after the bracketed host", spec)
}
// build programmatically instead:
spec := fmt.Sprintf("[%s]:%d:%s:%d", v6Host, localPort, rHost, rPort) Type guard
func isBracketedV6Spec(s string) bool {
return strings.HasPrefix(s, "[") && strings.Contains(s, "]:")
} Try / catch
if idx := strings.Index(spec, "]:"); idx == -1 {
// unbalanced bracket: reject with a hint showing the canonical form;
// do not attempt to auto-close brackets — that hides the real typo
} Prevention
- Generate IPv6 specs with Sprintf("[%s]:...") rather than typing brackets by hand.
- Add a regexp pre-check ^\[[0-9a-fA-F:]+\]: in wrapper scripts.
- Codemod existing configs: any forward value starting with '[' must contain ']:'.
When it happens
Trigger: `-L [::1:8080:host:80 peer` (missing closing bracket), `-L [fe80::1` (bracket opened, never closed, no colon-bracket sequence), or a spec where the ']' exists but is not immediately followed by ':' such as `[::1]8080:...`. The earlier router in parsePortForwardSpec only sends specs here when they start with '[' AND contain ']:' — so in practice this branch is reached via direct calls or malformed mixes; the more common user-visible path for a broken bracket is error 376 instead.
Common situations: Hand-typing IPv6 specs and dropping the closing bracket; find/replace operations that strip ']' but leave '['; specs assembled by concatenation where the ']:' separator variable is empty.
Related errors
- invalid port forward specification: %s
- invalid IPv6 port forward specification: %s (expected [ipv6]
- 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/094ea5f649d3dde7.
Report an issue: GitHub.