netbirdio/netbird · error
waiting sso login failed with: %v
Error message
waiting sso login failed with: %v
What it means
handleSSOLogin's WaitSSOLogin long-poll RPC to the daemon failed. The daemon blocks waiting for the IdP callback after the user opens the verification URI; this error appears when the CLI's context is cancelled (Ctrl+C), the daemon-side wait times out or expires, the daemon loses its connection to management mid-wait, or the gRPC transport drops.
Source
Thrown at client/cmd/login.go:357
if err := server.RestoreResidualState(ctx, profilemanager.NewServiceManager(configFilePath).GetStatePath()); err != nil {
log.Warnf("failed to restore residual state: %v", err)
}
nbnet.Init()
err = foregroundLogin(ctx, cmd, config, setupKey, activeProf.ID)
if err != nil {
return fmt.Errorf("foreground login failed: %v", err)
}
cmd.Println("Logging successfully")
return nil
}
func handleSSOLogin(ctx context.Context, cmd *cobra.Command, loginResp *proto.LoginResponse, client proto.DaemonServiceClient, pm *profilemanager.ProfileManager) error {
openURL(cmd, loginResp.VerificationURIComplete, loginResp.UserCode, noBrowser, showQR)
resp, err := client.WaitSSOLogin(ctx, &proto.WaitSSOLoginRequest{UserCode: loginResp.UserCode, Hostname: hostName})
if err != nil {
return fmt.Errorf("waiting sso login failed with: %v", err)
}
if resp.Email != "" {
err = pm.SetActiveProfileState(&profilemanager.ProfileState{
Email: resp.Email,
})
if err != nil {
log.Warnf("failed to set active profile email: %v", err)
}
}
return nil
}
func foregroundLogin(ctx context.Context, cmd *cobra.Command, config *profilemanager.Config, setupKey string, profileID profilemanager.ID) error {
authClient, err := auth.NewAuth(ctx, config.PrivateKey, config.ManagementURL, config)
if err != nil {
return fmt.Errorf("failed to create auth client: %v", err)View on GitHub (pinned to 93e97f4bf1)
Solutions
- Rerun 'netbird login' and complete the browser step promptly (mind the code expiry window)
- Ensure the daemon stays up during the flow (netbird service status) and check its logs
- Verify daemon-to-management connectivity and IdP health
- If aborting intentionally, Ctrl+C early rather than letting the code expire confusingly
Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm the daemon connection is alive before entering the long wait
if _, err := client.Status(ctx, &proto.StatusRequest{}); err != nil {
return fmt.Errorf("daemon unavailable before SSO wait: %w", err)
} Try / catch
resp, err := client.WaitSSOLogin(ctx, &proto.WaitSSOLoginRequest{...})
if err != nil {
if ctx.Err() != nil {
return fmt.Errorf("sso wait canceled: %w", err)
}
return fmt.Errorf("waiting sso login failed with: %w", err)
} Prevention
- Complete the browser step immediately after the code renders
- Use a CLI-side context with a timeout longer than the code lifetime so expiry is reported as deadline, not hang
- Script wrappers should check daemon liveness first to distinguish transport drops from auth failures
When it happens
Trigger: User aborts the command before completing browser auth; device/user code expires before approval; daemon restarted or crashed during the wait; management connection lost; ctx deadline exceeded on the CLI side.
Common situations: Browser auth left unfinished in a remote SSH session; IdP slow or down (SAML/OIDC latency) so the code expires; Daemon crash-looping or being upgraded mid-login
Related errors
- management client is not initialised
- wait for extend session: %v
- switch profile: %v
- switch profile on daemon: %v
- unable to get daemon status: %v
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/54a35f9b3ffb6d25.
Report an issue: GitHub.