{"record":{"id":"9d76e28984b0aab5","repo":"netbirdio/netbird","slug":"remote-port-forward-s-w","errorCode":null,"errorMessage":"remote port forward %s: %w","messagePattern":"remote port forward (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/ssh.go","lineNumber":623,"sourceCode":"\t\t\treturn nil\n\t\t}\n\n\t\treturn fmt.Errorf(\"open terminal: %w\", err)\n\t}\n\treturn nil\n}\n\n// startPortForwarding starts local and remote port forwarding based on command line flags\nfunc startPortForwarding(ctx context.Context, c *sshclient.Client, cmd *cobra.Command) error {\n\tfor _, forward := range localForwards {\n\t\tif err := parseAndStartLocalForward(ctx, c, forward, cmd); err != nil {\n\t\t\treturn fmt.Errorf(\"local port forward %s: %w\", forward, err)\n\t\t}\n\t}\n\n\tfor _, forward := range remoteForwards {\n\t\tif err := parseAndStartRemoteForward(ctx, c, forward, cmd); err != nil {\n\t\t\treturn fmt.Errorf(\"remote port forward %s: %w\", forward, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// parseAndStartLocalForward parses and starts a local port forward (-L)\nfunc parseAndStartLocalForward(ctx context.Context, c *sshclient.Client, forward string, cmd *cobra.Command) error {\n\tlocalAddr, remoteAddr, err := parsePortForwardSpec(forward)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := validateDestinationPort(remoteAddr); err != nil {\n\t\treturn fmt.Errorf(\"invalid remote address: %w\", err)\n\t}\n\n\tlog.Debugf(\"Local port forwarding: %s -> %s\", localAddr, remoteAddr)","sourceCodeStart":605,"sourceCodeEnd":641,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/ssh.go#L605-L641","documentation":"Returned by startPortForwarding when parseAndStartRemoteForward rejects one -R/--remote-forward spec. Structurally identical to the local case: the wrap names the failing spec and the cause is either parsePortForwardSpec (colon structure) or validateDestinationPort applied to the local address — in the -R flow the 'destination' the validator checks is the localAddr the remote side will dial back to.","triggerScenarios":"`netbird ssh -R 9000:localhost peer` (two parts, second not a unix path), `-R 9000:localhost:0` (local port 0), `-R 9000:localhost:70000` (out of range), `-R bindhost:9000:localhost:80:extra` (5 parts), or any spec whose validated local endpoint fails SplitHostPort/Atoi/range checks.","commonSituations":"Mirroring an OpenSSH -R habit of omitting the local port; expecting the remote side to pick the port; specs built from variables where one segment is empty; forgetting that in -R the last host:port pair is the local target your machine serves.","solutions":["Use the accepted forms with the local target fully specified: -R [remote_host:]remote_port:local_host:local_port, local port 1-65535 (e.g., -R 9000:localhost:8080).","Give the local endpoint a concrete non-zero port — 0 is rejected because the remote side must connect to something definite.","Bracket IPv6 bind hosts and keep the spec to 2-4 colon parts.","Check the wrapped tail (`invalid local address: ...`) to see exactly which sub-check failed, then fix that segment."],"exampleFix":"# before\nnetbird ssh -R 9000:localhost peer1\n# -> start port forwarding: remote port forward 9000:localhost: invalid port forward specification ...\n\n# after\nnetbird ssh -R 9000:localhost:8080 peer1","handlingStrategy":"validation","validationCode":"// -R grammar: [remote_host:]remote_port:local_host:local_port\nfunc buildRemoteForward(remotePort int, localHost string, localPort int) (string, error) {\n\tif remotePort < 1 || remotePort > 65535 || localPort < 1 || localPort > 65535 {\n\t\treturn \"\", fmt.Errorf(\"ports must be 1-65535, got remote=%d local=%d\", remotePort, localPort)\n\t}\n\tif localHost == \"\" {\n\t\tlocalHost = \"127.0.0.1\"\n\t}\n\treturn fmt.Sprintf(\"%d:%s:%d\", remotePort, localHost, localPort), nil\n}","typeGuard":null,"tryCatchPattern":"if err := parseAndStartRemoteForward(ctx, c, forward, cmd); err != nil {\n\t// parse or local-endpoint port validation failed on this spec;\n\t// report and continue/abort — no listener was created for it\n\tlog.Printf(\"skip remote forward %q: %v\", forward, err)\n}","preventionTips":["Remember -R's tail is the LOCAL endpoint your machine serves — give it host:port explicitly, never 0.","Use numeric ports only; service names are rejected by Atoi.","In templates, default unset local ports to the service's real port, not 0 or empty.","Pre-validate with the same colon-count and port-range checks you use for -L."],"tags":["go","ssh","port-forwarding","validation","cli"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}