{"record":{"id":"094ea5f649d3dde7","repo":"netbirdio/netbird","slug":"invalid-ipv6-port-forward-specification-s","errorCode":null,"errorMessage":"invalid IPv6 port forward specification: %s","messagePattern":"invalid IPv6 port forward specification: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/ssh.go","lineNumber":769,"sourceCode":"\t}\n\tlocalAddr := \"localhost:\" + parts[0]\n\tremoteAddr := parts[1] + \":\" + parts[2]\n\treturn localAddr, remoteAddr, nil\n}\n\n// parseFourPartForwardSpec handles \"host:port:host:hostport\" format.\nfunc parseFourPartForwardSpec(parts []string) (string, string, error) {\n\tlocalHost := normalizeLocalHost(parts[0])\n\tlocalAddr := localHost + \":\" + parts[1]\n\tremoteAddr := parts[2] + \":\" + parts[3]\n\treturn localAddr, remoteAddr, nil\n}\n\n// parseIPv6ForwardSpec handles \"[host]:port:host:hostport\" format.\nfunc parseIPv6ForwardSpec(spec string) (string, string, error) {\n\tidx := strings.Index(spec, \"]:\")\n\tif idx == -1 {\n\t\treturn \"\", \"\", fmt.Errorf(\"invalid IPv6 port forward specification: %s\", spec)\n\t}\n\n\tipv6Host := spec[:idx+1]\n\tremaining := spec[idx+2:]\n\n\tparts := strings.Split(remaining, \":\")\n\tif len(parts) != 3 {\n\t\treturn \"\", \"\", fmt.Errorf(\"invalid IPv6 port forward specification: %s (expected [ipv6]:port:host:hostport)\", spec)\n\t}\n\n\tlocalAddr := ipv6Host + \":\" + parts[0]\n\tremoteAddr := parts[1] + \":\" + parts[2]\n\treturn localAddr, remoteAddr, nil\n}\n\n// isUnixSocket checks if a path is a Unix socket path.\nfunc isUnixSocket(path string) bool {\n\treturn strings.HasPrefix(path, \"/\") || strings.HasPrefix(path, \"./\")","sourceCodeStart":751,"sourceCodeEnd":787,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/ssh.go#L751-L787","documentation":"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.","triggerScenarios":"`-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.","commonSituations":"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.","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."],"exampleFix":"# before\nnetbird ssh -L '[::1:8080:host:80' peer1\n# -> invalid IPv6 port forward specification: [::1:8080:host:80\n\n# after\nnetbird ssh -L '[::1]:8080:host:80' peer1","handlingStrategy":"validation","validationCode":"if strings.HasPrefix(spec, \"[\") && !strings.Contains(spec, \"]:\") {\n\treturn fmt.Errorf(\"IPv6 spec %q missing ']:\" + \"' after the bracketed host\", spec)\n}\n// build programmatically instead:\nspec := fmt.Sprintf(\"[%s]:%d:%s:%d\", v6Host, localPort, rHost, rPort)","typeGuard":"func isBracketedV6Spec(s string) bool {\n\treturn strings.HasPrefix(s, \"[\") && strings.Contains(s, \"]:\")\n}","tryCatchPattern":"if idx := strings.Index(spec, \"]:\"); idx == -1 {\n\t// unbalanced bracket: reject with a hint showing the canonical form;\n\t// do not attempt to auto-close brackets — that hides the real typo\n}","preventionTips":["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 ']:'."],"tags":["go","ssh","port-forwarding","ipv6","validation"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}