{"record":{"id":"161f5531438082da","repo":"mastra-ai/mastra","slug":"xai-device-authorization-response-missing-required","errorCode":null,"errorMessage":"xAI device authorization response missing required fields","messagePattern":"xAI device authorization response missing required fields","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/auth/providers/xai.ts","lineNumber":119,"sourceCode":"export async function startXAIDeviceLogin(options?: { signal?: AbortSignal }): Promise<XAIDeviceLoginPending> {\n  const response = await postForm(DEVICE_CODE_URL, { client_id: CLIENT_ID, scope: SCOPE }, options?.signal);\n\n  if (!response.ok) {\n    const text = await response.text().catch(() => '');\n    throw new Error(`Failed to initiate xAI device authorization: ${response.status}${text ? ` ${text}` : ''}`);\n  }\n\n  const data = (await response.json()) as {\n    device_code?: string;\n    user_code?: string;\n    verification_uri?: string;\n    verification_uri_complete?: string;\n    interval?: number;\n    expires_in?: number;\n  };\n\n  if (!data.device_code || !data.user_code || !data.verification_uri) {\n    throw new Error('xAI device authorization response missing required fields');\n  }\n\n  const url = validateVerificationUri(data.verification_uri_complete ?? data.verification_uri);\n\n  return {\n    deviceCode: data.device_code,\n    userCode: data.user_code,\n    url,\n    instructions: `Enter code: ${data.user_code}`,\n    state: createDeviceCodePollState({\n      intervalSeconds: data.interval,\n      expiresInSeconds: typeof data.expires_in === 'number' && data.expires_in > 0 ? data.expires_in : 600,\n    }),\n  };\n}\n\nasync function pollXAITokenOnce(\n  pending: XAIDeviceLoginPending,","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/auth/providers/xai.ts#L101-L137","documentation":"After a successful (2xx) device-authorization call, startXAIDeviceLogin requires device_code, user_code, and verification_uri to be present. If any is missing from the JSON body, the response cannot drive the device flow and this error is thrown.","triggerScenarios":"postForm to DEVICE_CODE_URL returns 2xx but the parsed JSON lacks one of device_code, user_code, or verification_uri.","commonSituations":"A gateway/proxy returns a 2xx with an unexpected body (e.g. login page or empty JSON); xAI API contract change; pointing DEVICE_CODE_URL at a wrong endpoint that still answers 200.","solutions":["Log the raw 2xx response body to see which fields are missing.","Confirm the device-code endpoint URL is the official xAI one, not an overridden or mocked URL.","Bypass intercepting proxies/captive portals for xAI API hosts.","Retry; if persistent, check for a provider API change and upgrade the SDK."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"function isCompleteDeviceAuthResponse(b: unknown): b is { device_code: string; user_code: string; verification_uri: string } {\n  const r = (b ?? {}) as Record<string, unknown>;\n  return typeof r.device_code === 'string' && r.device_code.length > 0\n    && typeof r.user_code === 'string' && r.user_code.length > 0\n    && typeof r.verification_uri === 'string' && r.verification_uri.length > 0;\n}","typeGuard":"function hasRequiredDeviceFields(data: unknown): data is { device_code: string; user_code: string; verification_uri: string } {\n  const r = (data ?? {}) as Record<string, unknown>;\n  return Boolean(r.device_code) && Boolean(r.user_code) && Boolean(r.verification_uri);\n}","tryCatchPattern":"try {\n  pending = await startXAIDeviceLogin();\n} catch (e) {\n  if (e instanceof Error && e.message.includes('missing required fields')) {\n    // 2xx but wrong body: log raw body, check endpoint/proxy, then retry\n    restartDeviceFlow();\n  }\n}","preventionTips":["Point DEVICE_CODE_URL at the official xAI endpoint only","Bypass proxies/captive portals that can return 2xx with HTML or empty JSON","Validate response shape (as above) when stubbing the endpoint in tests","Retry once on malformed 2xx bodies before failing the flow"],"tags":["oauth","xai","device-flow","response-validation"],"backgroundTag":"oauth-device-response-missing-fields","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}