{"record":{"id":"1de364c183086ab0","repo":"Wei-Shaw/sub2api","slug":"xai-device-verification-did-not-reach-consent-page","errorCode":null,"errorMessage":"xAI device verification did not reach consent page","messagePattern":"xAI device verification did not reach consent page","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/internal/pkg/xai/sso_device.go","lineNumber":158,"sourceCode":"\t}\n\n\tstatus, _, _, err = f.do(ctx, http.MethodGet, device.VerificationURIComplete, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif status < 200 || status >= 400 {\n\t\treturn nil, fmt.Errorf(\"open xAI device verification page: %w\", SSOHTTPError{Status: status})\n\t}\n\n\tstatus, finalURL, _, err = f.do(ctx, http.MethodPost, SSOVerifyURL, url.Values{\"user_code\": {device.UserCode}})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif status < 200 || status >= 400 {\n\t\treturn nil, fmt.Errorf(\"verify xAI device code: %w\", SSOHTTPError{Status: status})\n\t}\n\tif !strings.Contains(finalURL, \"consent\") {\n\t\treturn nil, errors.New(\"xAI device verification did not reach consent page\")\n\t}\n\n\tstatus, finalURL, _, err = f.do(ctx, http.MethodPost, SSOApproveURL, url.Values{\n\t\t\"user_code\":      {device.UserCode},\n\t\t\"action\":         {\"allow\"},\n\t\t\"principal_type\": {\"User\"},\n\t\t\"principal_id\":   {\"\"},\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif status < 200 || status >= 400 {\n\t\treturn nil, fmt.Errorf(\"approve xAI device code: %w\", SSOHTTPError{Status: status})\n\t}\n\tif !strings.Contains(finalURL, \"done\") {\n\t\treturn nil, errors.New(\"xAI device approval did not reach done page\")\n\t}\n","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/Wei-Shaw/sub2api/blob/073e92d17178a1ccdb0a27017f572f10c9c7ab62/backend/internal/pkg/xai/sso_device.go#L140-L176","documentation":"After GET-ing the verification_uri_complete and POST-ing the user_code to the verify endpoint, the flow checks that the final (post-redirect) URL contains 'consent'. If it does not, xAI did not land the session on the consent page, meaning the user_code was rejected, the session is not authenticated, or the flow was redirected somewhere unexpected (e.g. a login page).","triggerScenarios":"The POST to SSOVerifyURL succeeds HTTP-wise but redirects to a login/challenge page instead of the consent page: expired or mistyped user_code, session cookies not accepted, xAI adding an intermediate step (captcha, email verification), or a redirect loop that ends elsewhere.","commonSituations":"SSO session token invalidated between start and verify; xAI deploys an extra auth step; cookie jar not seeded correctly (seedSSOCookies skipped or cookie policy blocking them); region-specific consent variants that use a different URL keyword.","solutions":["Verify the session token is still valid by hitting an authenticated xAI endpoint first.","Ensure the http.Client used by the flow has a working cookie jar and that seedSSOCookies ran.","Retry with a brand-new device flow (fresh user_code).","If persistent, xAI likely changed the flow: log the final URL to see where it landed and adjust the 'consent' check."],"exampleFix":"// before\nif !strings.Contains(finalURL, \"consent\") {\n    return nil, errors.New(\"xAI device verification did not reach consent page\")\n}\n\n// after (diagnostics: record where it actually landed)\nif !strings.Contains(finalURL, \"consent\") {\n    return nil, fmt.Errorf(\"xAI device verification did not reach consent page (landed on %s)\", finalURL)\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := flow.Start(ctx); err != nil {\n    if strings.Contains(err.Error(), \"did not reach consent page\") {\n        // stale cookies or unauthenticated session: restart with fresh flow + token\n        return restartFlowWithFreshToken()\n    }\n    return err\n}","preventionTips":["Validate the session token with a cheap authenticated call before the device flow","Always run with a cookie jar","Log finalURL on failure to distinguish login-redirect from captcha-redirect"],"tags":["xai","sso","device-flow","redirect"],"backgroundTag":null,"analyzedSha":"073e92d17178a1ccdb0a27017f572f10c9c7ab62","analyzedAt":"2026-08-15T14:33:00.750Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}