fatedier/frp · critical
login to the server failed: %v. With loginFailExit enabled,
Error message
login to the server failed: %v. With loginFailExit enabled, no additional retries will be attempted
What it means
Returned from Service.Run when the initial login to frps did not succeed and loginFailExit is enabled (the default). loopLoginUntilSuccess gave up (or the context was cancelled with a cancelErr), svr.ctl is nil, so frpc stops and reports the login failure reason with a note that no retries will be attempted.
Source
Thrown at client/service.go:267
}
if svr.webServer != nil {
webServer := svr.webServer
go func() {
log.Infof("admin server listen on %s", webServer.Address())
if err := webServer.Run(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Warnf("admin server exit with error: %v", err)
}
}()
}
// first login to frps
svr.loopLoginUntilSuccess(10*time.Second, lo.FromPtr(svr.common.LoginFailExit))
if svr.ctl == nil {
cancelCause := cancelErr{}
_ = errors.As(context.Cause(svr.ctx), &cancelCause)
svr.stop()
return fmt.Errorf("login to the server failed: %v. With loginFailExit enabled, no additional retries will be attempted", cancelCause.Err)
}
go svr.keepControllerWorking()
<-svr.ctx.Done()
svr.stop()
return nil
}
func (svr *Service) keepControllerWorking() {
<-svr.ctl.Done()
// There is a situation where the login is successful but due to certain reasons,
// the control immediately exits. It is necessary to limit the frequency of reconnection in this case.
// The interval for the first three retries in 1 minute will be very short, and then it will increase exponentially.
// The maximum interval is 20 seconds.
wait.BackoffUntil(func() (bool, error) {
// loopLoginUntilSuccess is another layer of loop that will continuously attempt toView on GitHub (pinned to 6c8a8d0a97)
Solutions
- Read the %v portion — it contains the real login error (dial timeout, auth failure, tls error) and dictates the fix.
- Verify serverAddr/serverPort and network reachability of frps (telnet/curl the port).
- Align auth settings (auth.method, auth.token) and TLS settings on both frpc and frps.
- If frps may start later than frpc, set loginFailExit = false so frpc retries instead of exiting.
Example fix
# before (frpc.toml) loginFailExit = true serverAddr = "10.0.0.1" serverPort = 7000 # after (when frps may be temporarily down) loginFailExit = false
Defensive patterns
Strategy: fallback
Validate before calling
// Pre-flight: can we reach frps before launching frpc?
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", serverAddr, serverPort), 3*time.Second)
if err != nil { return fmt.Errorf("frps unreachable: %w", err) }
conn.Close() Try / catch
err := svr.Run(ctx)
if err != nil && strings.Contains(err.Error(), "login to the server failed") {
// inspect embedded cause: auth vs network; fix auth.token / serverAddr, or set loginFailExit=false and let systemd restart frpc
} Prevention
- Set loginFailExit=false when frpc may start before frps (e.g. docker-compose).
- Pre-check connectivity and auth token before deploying.
- Keep auth and TLS config in sync across frpc/frps in one repo.
When it happens
Trigger: Starting frpc with loginFailExit = true against an unreachable/misauthenticated frps: wrong server address/port, TLS mismatch (transport.tls vs frps proxyProtocol/tls settings), auth.token mismatch, or firewall blocking. The context cancellation cause carries the concrete login error.
Common situations: First-run misconfiguration (serverAddr typo, forgot serverPort); auth method/token mismatch after enabling token auth on frps; frps behind LB terminating TLS; running frpc as a one-shot job where infinite retry is unwanted, hence loginFailExit=true.
Related errors
- loginRespMsg.Error
- create control crypto read writer: %w
- unexpected frame type %d, want %d
- create encryption stream error: %w
- failed to load config from aggregator: %w
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/dcf9607216b59f1b.
Report an issue: GitHub.