fatedier/frp · error
ps.Err
Error message
ps.Err
What it means
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.
Source
Thrown at pkg/ssh/server.go:398
defer ticker.Stop()
timer := time.NewTimer(timeout)
defer timer.Stop()
statusExporter := s.vc.Service().StatusExporter()
for {
select {
case <-ticker.C:
ps, ok := statusExporter.GetProxyStatus(name)
if !ok {
continue
}
switch ps.Phase {
case proxy.ProxyPhaseRunning:
return ps, nil
case proxy.ProxyPhaseStartErr, proxy.ProxyPhaseClosed:
return ps, errors.New(ps.Err)
}
case <-timer.C:
return nil, fmt.Errorf("wait proxy status ready timeout")
case <-s.doneCh:
return nil, fmt.Errorf("ssh tunnel server closed")
}
}
}
View on GitHub (pinned to 6c8a8d0a97)
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
Defensive patterns
Strategy: retry
Try / catch
ps, err := tunnelServer.WaitProxyReady(name, timeout) // conceptual
if err != nil {
if strings.Contains(err.Error(), "timeout") {
// retry after confirming the proxy is registered
}
// ps.Err content names the real proxy failure; fix root cause on the frpc side
return fmt.Errorf("proxy %s failed: %w", name, err)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- exec configuration is required when type is 'exec'
- file path cannot be empty
- exec command cannot be empty
- exec env name cannot be empty
- exec env name cannot contain '='
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/9cefc3f719496733.
Report an issue: GitHub.