{"record":{"id":"7778227e559da5df","repo":"decolua/9router","slug":"missing-xai-authorization-code","errorCode":null,"errorMessage":"Missing xAI authorization code","messagePattern":"Missing xAI authorization code","errorType":"validation","errorClass":"Error","httpStatus":500,"severity":"error","filePath":"src/app/api/oauth/[provider]/[action]/route.js","lineNumber":45,"sourceCode":"  stopWindsurfProxy,\n  registerWindsurfSession,\n  getWindsurfSessionStatus,\n  clearWindsurfSession,\n  startZedProxy,\n  stopZedProxy,\n  registerZedSession,\n  getZedSessionStatus,\n  clearZedSession,\n} from \"@/lib/oauth/utils/server\";\nimport { detectIdeInstalled } from \"@/lib/oauth/utils/ideDetect\";\nimport { ZED_HOSTED_CONFIG } from \"@/lib/oauth/constants/oauth\";\n\nasync function completeXaiManualCode(code, state) {\n  const session = state ? getXaiSessionStatus(state) : null;\n  if (!session) {\n    throw new Error(\"xAI OAuth session not found; restart the login flow and paste the code again\");\n  }\n  if (!code) throw new Error(\"Missing xAI authorization code\");\n\n  try {\n    const tokenData = await exchangeTokens(\n      \"xai\",\n      code,\n      session.redirectUri,\n      session.codeVerifier,\n      state\n    );\n    const connection = await createProviderConnection({\n      provider: \"xai\",\n      authType: \"oauth\",\n      ...tokenData,\n      expiresAt: tokenData.expiresIn\n        ? new Date(Date.now() + tokenData.expiresIn * 1000).toISOString()\n        : null,\n      testStatus: \"active\",\n    });","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/app/api/oauth/[provider]/[action]/route.js#L27-L63","documentation":"completeXaiManualCode requires the authorization code returned by the xAI login page. After verifying the state/session it checks that a non-empty code string was supplied; if not it throws before attempting the token exchange. The code is required to swap for access/refresh tokens.","triggerScenarios":"Submitting the xAI manual-code callback (/api/oauth/xai/<action>) with code missing, empty string, or whitespace-only while the state/session lookup succeeded.","commonSituations":"User pastes only the state or the redirect URL without extracting the code query param; a copy-paste truncated the code; a script automation sent the request without parsing ?code= from the redirect.","solutions":["Copy the full code=<...> query parameter from the xAI redirect URL and pass it as code.","Re-do the login flow if the redirect URL was lost — codes are single-use.","Verify the request sends code as a query param or body field, not null/undefined."],"exampleFix":"// before\nconst res = await fetch(`/api/oauth/xai/callback?state=${state}`);\n// after\nconst res = await fetch(`/api/oauth/xai/callback?code=${encodeURIComponent(code)}&state=${state}`);","handlingStrategy":"validation","validationCode":"const params = new URL(redirectUrl).searchParams;\nconst code = params.get(\"code\");\nif (!code) throw new Error(\"Redirect URL has no ?code= parameter\");","typeGuard":"const hasCode = (c) => typeof c === \"string\" && c.trim().length > 0;","tryCatchPattern":"try {\n  await submitXaiCode(code, state);\n} catch (e) {\n  if (e.message === \"Missing xAI authorization code\") {\n    console.error(\"Extract code= from the full redirect URL and resend\");\n  } else throw e;\n}","preventionTips":["Parse the code query param programmatically instead of manual copy-paste","Send the entire redirect URL content — don't truncate long codes","Check for null/undefined code before calling the callback endpoint"],"tags":["oauth","xai","validation"],"backgroundTag":"missing-oauth-code","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}