netbirdio/netbird · error
failed to get OAuth flow: %v
Error message
failed to get OAuth flow: %v
What it means
Thrown by Auth.foregroundGetTokenInfo when auth.Auth.GetOAuthFlow fails to create an OAuth flow on top of the existing management connection. GetOAuthFlow fetches the IdP provider configuration from the management service before any browser login can start, so a broken transport or an unusable IdP setup on the management side surfaces here. The message wraps the underlying error verbatim; the app sees it as 'interactive sso login failed: ...' on the ErrListener, both from Auth.Login and from Client.ExtendAuthSession.
Source
Thrown at client/android/login.go:204
}
}
go urlOpener.OnLoginSuccess()
return nil
}
// loginHintSetter is implemented by both concrete flows (PKCE and device code)
// but absent from the OAuthFlow interface, hence the assertion below — the same
// way internal/auth wires it in authenticateWithPKCEFlow.
type loginHintSetter interface {
SetLoginHint(hint string)
}
func (a *Auth) foregroundGetTokenInfo(authClient *auth.Auth, urlOpener URLOpener, isAndroidTV bool) (*auth.TokenInfo, error) {
oAuthFlow, err := authClient.GetOAuthFlow(a.ctx, isAndroidTV)
if err != nil {
return nil, fmt.Errorf("failed to get OAuth flow: %v", err)
}
// An empty hint is deliberate, not a fallback: a fresh profile leaves the
// choice to the IdP. Switching accounts is done by switching or removing
// profiles, not by logging out — logout keeps the email.
if a.cfgPath != "" {
if hint := readProfileEmail(a.cfgPath); hint != "" {
if setter, ok := oAuthFlow.(loginHintSetter); ok {
setter.SetLoginHint(hint)
}
}
}
flowInfo, err := oAuthFlow.RequestAuthInfo(context.TODO())
if err != nil {
return nil, fmt.Errorf("getting a request OAuth flow info failed: %v", err)
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Verify the management URL passed to NewAuth is correct and reachable from the device
- Check the management service's IdP/SSO configuration (OIDC issuer, client ID, device flow support)
- Read the wrapped error: a transport error points to connectivity, a decode/validation error to management's IdP config
- Fix the cause and retry; every attempt builds a fresh flow, no state is poisoned
Example fix
// before auth, _ := android.NewAuth(cfgPath, mgmURL) // mgmURL typo or unreachable auth.Login(listener, urlOpener, false) // later: "interactive sso login failed: failed to get OAuth flow: ..." // after: probe management connectivity and SSO support first auth.SaveConfigIfSSOSupported(ssoListener) // only call Login once this reports success and sso==true
Defensive patterns
Strategy: try-catch
Validate before calling
// Probe management connectivity and SSO support before starting a browser login
auth.SaveConfigIfSSOSupported(new SSOListener() {
public void OnSuccess(boolean sso) { if (sso) auth.Login(errListener, urlOpener, false); }
public void OnError(Exception err) { /* surface the config/network problem; do not call Login yet */ }
}); Try / catch
// In the ErrListener passed to Login / ExtendAuthSession
func (l *listener) OnError(err error) {
if strings.Contains(err.Error(), "failed to get OAuth flow") {
// connectivity or management IdP config problem: check URL, network, TLS; safe to retry
}
} Prevention
- Validate the management URL before login; SaveConfigIfSSOSupported doubles as a connectivity probe
- Ensure the device trusts management's TLS certificate
- Keep management's OIDC configuration valid — a broken IdP config fails every client login
- Treat transport failures as retryable; the flow is stateless per attempt
When it happens
Trigger: Auth.Login with needsLogin=true, or Client.ExtendAuthSession, calls GetOAuthFlow(ctx, isAndroidTV). It fails when the management connection cannot fetch or decode the OAuth provider info: management unreachable, TLS handshake failure, an HTTP error from the management API, or a malformed/invalid IdP configuration returned by management.
Common situations: Wrong or unreachable management URL passed to NewAuth, untrusted self-signed certificate on management, device behind a captive portal, management's OIDC issuer or client ID misconfigured, device clock skew breaking TLS verification.
Related errors
- getting a request OAuth flow info failed: %v
- waiting for browser login failed: %v
- session extend already in progress
- failed to create auth client: %v
- management client is not initialised
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/4ad3204154fd279e.
Report an issue: GitHub.