netbirdio/netbird · error

getting a request OAuth flow info failed: %v

Error message

getting a request OAuth flow info failed: %v

What it means

Thrown after the OAuth flow object exists, when oAuthFlow.RequestAuthInfo fails: the flow asks the IdP for a verification URI and user code (device flow) or prepares the PKCE request. The call uses context.TODO(), so it never cancels and fails only on a real error — an HTTP failure from the IdP, an unreachable IdP, or the IdP rejecting the OAuth client. Wrapped verbatim and surfaced as 'interactive sso login failed: ...' on the listener.

Source

Thrown at client/android/login.go:220

	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)
	}

	go urlOpener.Open(flowInfo.VerificationURIComplete, flowInfo.UserCode)

	tokenInfo, err := oAuthFlow.WaitToken(a.ctx, flowInfo)
	if err != nil {
		return nil, fmt.Errorf("waiting for browser login failed: %v", err)
	}

	return &tokenInfo, nil
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Confirm the device can reach the IdP endpoints, not just management
  2. Check the OAuth client on the IdP: client_id still valid, device/PKCE flow allowed for it
  3. Inspect the wrapped HTTP status to distinguish IdP rejection from connectivity
  4. Retry the login; each attempt requests fresh auth info

Example fix

// before: single attempt, any hiccup fails the flow
auth.Login(listener, urlOpener, false)

// after: in the ErrListener, retry once on transient RequestAuthInfo failures
func (l *loginListener) OnError(err error) {
	if strings.Contains(err.Error(), "getting a request OAuth flow info failed") && !l.retried {
		l.retried = true
		go auth.Login(l, urlOpener, false) // fresh auth info is requested each attempt
		return
	}
	l.show(err)
}
Defensive patterns

Strategy: retry

Validate before calling

// Before Login, confirm general egress works — the SaveConfigIfSSOSupported probe exercises the management path
// and surfaces network problems before the IdP call is attempted.

Try / catch

// In the ErrListener: retry once with backoff when RequestAuthInfo failed transiently
if strings.Contains(err.Error(), "getting a request OAuth flow info failed") && !retried {
	retried = true
	time.AfterFunc(2*time.Second, func() { go auth.Login(l, urlOpener, false) })
	return
}

Prevention

When it happens

Trigger: foregroundGetTokenInfo calls RequestAuthInfo(context.TODO()) right after GetOAuthFlow succeeded; the POST to the IdP device-authorization endpoint (or PKCE setup) fails because the network dropped between the management check and the IdP call, the IdP is down, the OAuth client_id is invalid/deleted, or the IdP returns a non-2xx response.

Common situations: Management reachable but the IdP blocked or slow from the mobile network, IdP outage or maintenance, OAuth client deleted or expired on the IdP side, Android TV devices with flaky Wi-Fi.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/8ccae491222cef1a. Report an issue: GitHub.