{"record":{"id":"9cefc3f719496733","repo":"fatedier/frp","slug":"ps-err","errorCode":null,"errorMessage":"ps.Err","messagePattern":"ps\\.Err","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/ssh/server.go","lineNumber":398,"sourceCode":"\tdefer ticker.Stop()\n\n\ttimer := time.NewTimer(timeout)\n\tdefer timer.Stop()\n\n\tstatusExporter := s.vc.Service().StatusExporter()\n\n\tfor {\n\t\tselect {\n\t\tcase <-ticker.C:\n\t\t\tps, ok := statusExporter.GetProxyStatus(name)\n\t\t\tif !ok {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch ps.Phase {\n\t\t\tcase proxy.ProxyPhaseRunning:\n\t\t\t\treturn ps, nil\n\t\t\tcase proxy.ProxyPhaseStartErr, proxy.ProxyPhaseClosed:\n\t\t\t\treturn ps, errors.New(ps.Err)\n\t\t\t}\n\t\tcase <-timer.C:\n\t\t\treturn nil, fmt.Errorf(\"wait proxy status ready timeout\")\n\t\tcase <-s.doneCh:\n\t\t\treturn nil, fmt.Errorf(\"ssh tunnel server closed\")\n\t\t}\n\t}\n}\n","sourceCodeStart":380,"sourceCodeEnd":407,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/ssh/server.go#L380-L407","documentation":"Created with errors.New(ps.Err) in TunnelServer.waitProxyStatusReady (pkg/ssh/server.go:398). When an SSH-tunnel visitor (ssh tunnel gateway) requests a proxy, frpc polls the status exporter; if the proxy enters ProxyPhaseStartErr or ProxyPhaseClosed, the proxy's own error string is surfaced verbatim. The message is therefore dynamic — the real cause comes from the proxy that failed to start on the client side.","triggerScenarios":"Using the frps ssh tunnel gateway (`frps --strict-ssh-tunnel` / ssh gateway port) to open a forward to a proxy whose client-side setup fails: port conflict on frpc host, unreachable local service, plugin exec failure, or auth/token rejection; proxy closes before reaching ProxyPhaseRunning.","commonSituations":"Remote port already bound on the frpc machine; local service behind the proxy down; token/auth mismatch between ssh session user and the frpc that owns the proxy; the 100ms polling observes StartErr shortly after NewProxy.","solutions":["Read the ps.Err content — it is the underlying proxy error (e.g. port bind failure); fix that root cause on the frpc side","Check frpc logs for the named proxy to see why it entered start-err/closed","Verify the remote port is free and the local service is reachable from frpc","If it is a race at startup, retry the ssh forward once the proxy is Running"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"ps, err := tunnelServer.WaitProxyReady(name, timeout) // conceptual\nif err != nil {\n    if strings.Contains(err.Error(), \"timeout\") {\n        // retry after confirming the proxy is registered\n    }\n    // ps.Err content names the real proxy failure; fix root cause on the frpc side\n    return fmt.Errorf(\"proxy %s failed: %w\", name, err)\n}","preventionTips":["Pre-check on the frpc host that the local service is up and the remote port is free before opening an ssh-gateway forward","Watch frpc logs for the proxy name; StartErr there mirrors the ps.Err surfaced by the ssh gateway"],"tags":["frp","go","ssh","gateway","proxy-status"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}