fatedier/frp · info
ssh tunnel server closed
Error message
ssh tunnel server closed
What it means
Returned by waitProxyStatusReady when the TunnelServer's doneCh is closed while it is still waiting for a proxy to become ready. doneCh is closed by the server's shutdown path, so this error means 'we did not learn the proxy's fate because the whole SSH tunnel server is going away' — a clean cancellation, not a proxy failure.
Source
Thrown at pkg/ssh/server.go:403
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
- Treat as transient: reconnect the SSH tunnel after the server comes back up.
- Operators: drain or wait for tunnel setup quiescence before restarting frps.
- Automation: distinguish this cancellation (retry) from 'wait proxy status ready timeout' (investigate proxy).
Defensive patterns
Strategy: try-catch
Try / catch
status, err := s.waitProxyStatusReady(name, timeout)
if err != nil {
if strings.Contains(err.Error(), "ssh tunnel server closed") {
return nil // clean cancellation during shutdown — not a failure
}
return err
} Prevention
- Distinguish this cancellation from real proxy failures before alerting.
- Operators: drain tunnel setup before restarting frps.
- Clients: auto-reconnect tunnels after the server returns.
When it happens
Trigger: frps shuts down or the SSH gateway listener is closed while an SSH tunnel session is still waiting for its proxy to register; context cancellation propagating through server Close().
Common situations: frps restart/redeploy while users have tunnels mid-creation; systemd stop; supervisor-driven rolling restarts.
Related errors
- channel for udp listener closed
- listener closed
- control manager is closed
- ps.Err
- send CloseProxy request to plugin errors: %s
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/23265344fc70cadd.
Report an issue: GitHub.