{"record":{"id":"3449b3f38b5b4690","repo":"fatedier/frp","slug":"parse-flags-from-ssh-client-error-v","errorCode":null,"errorMessage":"parse flags from ssh client error: %v","messagePattern":"parse flags from ssh client error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/ssh/server.go","lineNumber":111,"sourceCode":"\tif err != nil {\n\t\treturn err\n\t}\n\n\ts.sshConn = sshConn\n\n\taddr, extraPayload, err := s.waitForwardAddrAndExtraPayload(channels, requests, 3*time.Second)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tclientCfg, pc, helpMessage, err := s.parseClientAndProxyConfigurer(addr, extraPayload)\n\tif err != nil {\n\t\tif errors.Is(err, flag.ErrHelp) {\n\t\t\ts.writeToClient(helpMessage)\n\t\t\treturn nil\n\t\t}\n\t\ts.writeToClient(err.Error())\n\t\treturn fmt.Errorf(\"parse flags from ssh client error: %v\", err)\n\t}\n\tif err := clientCfg.Complete(); err != nil {\n\t\ts.writeToClient(fmt.Sprintf(\"failed to complete client config: %v\", err))\n\t\treturn fmt.Errorf(\"complete client config error: %v\", err)\n\t}\n\tif sshConn.Permissions != nil {\n\t\tclientCfg.User = util.EmptyOr(sshConn.Permissions.Extensions[\"user\"], clientCfg.User)\n\t}\n\tpc.Complete()\n\n\tvc, err := virtual.NewClient(virtual.ClientOptions{\n\t\tCommon: clientCfg,\n\t\tSpec: &msg.ClientSpec{\n\t\t\tType: \"ssh-tunnel\",\n\t\t\t// If ssh does not require authentication, then the virtual client needs to authenticate through a token.\n\t\t\t// Otherwise, once ssh authentication is passed, the virtual client does not need to authenticate again.\n\t\t\tAlwaysAuthPass: !s.sc.NoClientAuth,\n\t\t},","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/ssh/server.go#L93-L129","documentation":"Returned by the frp SSH tunnel server when the command string the client sent after connecting (the 'extra payload', e.g. \"tcp 127.0.0.1:22\") cannot be parsed into frpc proxy flags via the embedded cobra command. The raw parse error is also sent back to the client over the SSH channel before the wrapper error is returned, so the user usually sees the underlying reason on their terminal.","triggerScenarios":"Calling ssh with an unknown proxy type token (e.g. `ssh v0@host \"udp ...\"`), passing malformed flags (--remotePort not-a-number), unknown flags not registered in SSH mode, or a payload that fails cobra's ParseFlags. Not triggered by flag.ErrHelp, which prints usage and exits cleanly.","commonSituations":"Users assuming all frpc proxy types work over SSH (only tcp/http/https/tcpmux/stcp do); typos in flag names; copying an frpc.ini stanza into the ssh command line; shell quoting eating the payload so it arrives empty or split incorrectly.","solutions":["Read the message written back to your SSH session — it contains the exact cobra parse error before this wrapper fires.","Use a supported proxy type as the first token: tcp, http, https, tcpmux, or stcp.","Run `ssh -p port v0@host -- --help` (or an invalid flag) to get the full usage string listing accepted flags.","Quote the whole command as one argument: ssh v0@host \"tcp 127.0.0.1:22 --remotePort 6000\"."],"exampleFix":"# before\nssh -p 7000 v0@frps \"udp 127.0.0.1:53\"\n\n# after\nssh -p 7000 v0@frps \"tcp 127.0.0.1:53 --remotePort 6000\"","handlingStrategy":"validation","validationCode":"// validate an SSH tunnel command before sending it\nvar supportedSSHProxyTypes = []string{\"tcp\", \"http\", \"https\", \"tcpmux\", \"stcp\"}\n\nfunc ValidateTunnelCommand(cmd string) error {\n    fields := strings.Fields(cmd)\n    if len(fields) == 0 {\n        return fmt.Errorf(\"empty command\")\n    }\n    if !slices.Contains(supportedSSHProxyTypes, fields[0]) {\n        return fmt.Errorf(\"unsupported type %q, want one of %v\", fields[0], supportedSSHProxyTypes)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Quote the whole payload as a single ssh command argument.","Print usage (`-- --help`) when unsure which flags exist in SSH mode.","Remember only tcp/http/https/tcpmux/stcp are exposed over the SSH gateway."],"tags":["ssh","cli","parsing","user-input"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}