Wei-Shaw/sub2api · error

xAI OAuth redirected too many times

Error message

xAI OAuth redirected too many times

What it means

The manual redirect loop allows at most 8 hops (redirects 0..8 inclusive of the initial request). Exhausting the budget without a non-3xx final response yields this error. It protects against redirect loops between xAI auth endpoints.

Source

Thrown at backend/internal/pkg/xai/sso_device.go:305

		location := strings.TrimSpace(response.Header.Get("Location"))
		if location == "" {
			return response.StatusCode, currentURL, data, errors.New("xAI OAuth redirect missing Location")
		}
		base, _ := url.Parse(currentURL)
		next, err := url.Parse(location)
		if err != nil {
			return response.StatusCode, currentURL, data, err
		}
		currentURL = base.ResolveReference(next).String()
		if !safeXAIAuthURL(currentURL) {
			return response.StatusCode, currentURL, data, errors.New("xAI OAuth redirected to untrusted host")
		}
		if response.StatusCode == http.StatusSeeOther || ((response.StatusCode == http.StatusMovedPermanently || response.StatusCode == http.StatusFound) && currentMethod != http.MethodGet && currentMethod != http.MethodHead) {
			currentMethod = http.MethodGet
			currentForm = nil
		}
	}
	return 0, currentURL, nil, errors.New("xAI OAuth redirected too many times")
}

func seedSSOCookies(jar http.CookieJar, token string) {
	if jar == nil {
		return
	}
	for _, rawURL := range []string{SSOAccountsURL, OAuthIssuer + "/"} {
		target, err := url.Parse(rawURL)
		if err != nil {
			continue
		}
		jar.SetCookies(target, []*http.Cookie{
			{Name: "sso", Value: token, Path: "/", Secure: true, HttpOnly: true},
			{Name: "sso-rw", Value: token, Path: "/", Secure: true, HttpOnly: true},
		})
	}
}

View on GitHub (pinned to 073e92d171)

Solutions

  1. Ensure the http.Client has a cookie jar and cookies persist across hops (seedSSOCookies must have run).
  2. Log each hop URL to identify the loop participants.
  3. Retry with a fresh session token; stale state often causes ping-pong.
  4. Only if a legitimate chain needs more hops, raise the loop bound in sso_device.go.

Example fix

// client without cookie handling (loop-prone)
client := &http.Client{}

// after
client := &http.Client{
    Jar: jar, // required so auth cookies survive redirect hops
    CheckRedirect: http.ErrUseLastResponse, // flow reads Location itself
}
Defensive patterns

Strategy: validation

Validate before calling

// before invoking the flow
if client.Jar == nil {
    return errors.New("SSO device flow requires an http.Client with a CookieJar")
}

Try / catch

if err != nil && strings.Contains(err.Error(), "redirected too many times") {
    return restartFlowWithFreshToken() // loop almost always means cookie state was lost
}

Prevention

When it happens

Trigger: verify/approve endpoints bouncing between two or more URLs indefinitely (cookie not set, so each hop re-issues the redirect); or a genuinely long legitimate chain exceeding 8 hops.

Common situations: Cookie jar disabled or cookies rejected (Secure/SameSite attributes vs http:// test contexts), so xAI keeps redirecting to 'login' which redirects back; xAI incidents with redirect loops; region negotiation ping-pong.

Related errors


AI-assisted analysis of Wei-Shaw/sub2api@073e92d171 (2026-08-15). Data as JSON: /api/errors/b31bfbd5ac04ef9f. Report an issue: GitHub.