{"record":{"id":"1375b256d35ff75c","repo":"BloopAI/vibe-kanban","slug":"oauth-init-failed-res-status","errorCode":null,"errorMessage":"OAuth init failed (${res.status})","messagePattern":"OAuth init failed \\((.+?)\\)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/remote-web/src/shared/lib/api.ts","lineNumber":65,"sourceCode":"  email: string;\n};\n\nexport async function initOAuth(\n  provider: OAuthProvider,\n  returnTo: string,\n  appChallenge: string,\n): Promise<HandoffInitResponse> {\n  const res = await fetch(`${API_BASE}/v1/oauth/web/init`, {\n    method: \"POST\",\n    headers: { \"Content-Type\": \"application/json\" },\n    body: JSON.stringify({\n      provider,\n      return_to: returnTo,\n      app_challenge: appChallenge,\n    }),\n  });\n  if (!res.ok) {\n    throw new Error(`OAuth init failed (${res.status})`);\n  }\n  return res.json();\n}\n\nexport async function getAuthMethods(): Promise<AuthMethodsResponse> {\n  const res = await fetch(`${API_BASE}/v1/auth/methods`, {\n    cache: \"no-store\",\n  });\n  if (!res.ok) {\n    throw new Error(`Auth methods lookup failed (${res.status})`);\n  }\n  return res.json();\n}\n\nexport async function redeemOAuth(\n  handoffId: string,\n  appCode: string,\n  appVerifier: string,","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/BloopAI/vibe-kanban/blob/4deb7eca8f381f7cbc1f9d15515a9ab8f8009053/packages/remote-web/src/shared/lib/api.ts#L47-L83","documentation":"initOAuth starts the web OAuth flow by POSTing to ${API_BASE}/v1/oauth/web/init with the provider, return_to path, and PKCE app_challenge. If the server responds with any non-OK HTTP status, the function throws 'OAuth init failed (<status>)' instead of returning a handoff_id/authorize_url. This indicates the backend refused to create the OAuth handoff session.","triggerScenarios":"Calling initOAuth(provider, returnTo, appChallenge) where the POST /v1/oauth/web/init request fails: an unsupported/unknown provider value is sent (400/422), the server's OAuth provider credentials are not configured (500), the API base URL is wrong so a proxy returns 404, the server is down/overloaded (502/503), or rate limiting (429).","commonSituations":"Remote server deployed without GitHub/Google OAuth client ID/secret env vars; VITE_API_BASE_URL pointing at the wrong host so /v1/oauth/web/init 404s; user clicks 'Sign in with GitHub' while the backend is redeploying; provider name typo or new provider not yet supported by the deployed server version.","solutions":["Check the response status in the error and match it to server logs for /v1/oauth/web/init.","Verify the server has OAuth provider credentials configured (e.g. GITHUB_CLIENT_ID/SECRET, GOOGLE client env vars).","Confirm VITE_API_BASE_URL resolves to the correct remote API host that serves /v1/oauth/web/init.","Ensure the provider argument is one of 'github' | 'google' as defined by OAuthProvider.","Retry after server deployment/health issues clear (502/503/429 are often transient)."],"exampleFix":"// before\nconst provider = (new URLSearchParams(location.search).get('provider') ?? 'gitlab') as OAuthProvider;\nawait initOAuth(provider, returnTo, challenge);\n\n// after: only pass supported providers\nconst raw = new URLSearchParams(location.search).get('provider');\nconst provider: OAuthProvider = raw === 'google' ? 'google' : 'github';\nawait initOAuth(provider, returnTo, challenge);","handlingStrategy":"try-catch","validationCode":"// pre-validate before calling initOAuth\nconst providers: OAuthProvider[] = ['github', 'google'];\nif (!providers.includes(provider)) {\n  throw new Error(`Unsupported OAuth provider: ${provider}`);\n}\nif (!API_BASE && !location.pathname.startsWith('/')) {\n  throw new Error('VITE_API_BASE_URL is not configured');\n}","typeGuard":"function isHandoffInitResponse(x: unknown): x is { handoff_id: string; authorize_url: string } {\n  return typeof x === 'object' && x !== null\n    && typeof (x as any).handoff_id === 'string'\n    && typeof (x as any).authorize_url === 'string';\n}","tryCatchPattern":"let handoff: HandoffInitResponse;\ntry {\n  handoff = await initOAuth(provider, returnTo, appChallenge);\n} catch (e) {\n  const status = (e as Error).message.match(/\\((\\d+)\\)/)?.[1];\n  showError(`Could not start ${provider} sign-in (HTTP ${status ?? 'network'}). Check provider configuration or try again.`);\n  return;\n}\nwindow.location.assign(handoff.authorize_url);","preventionTips":["Configure OAuth client ID/secret env vars on the remote server before enabling the buttons.","Only pass 'github' or 'google' as provider values.","Verify VITE_API_BASE_URL at build/deploy time.","Monitor /v1/oauth/web/init for 5xx after deploys.","Disable OAuth buttons while the API health check fails."],"tags":["oauth","http","authentication"],"backgroundTag":"oauth-init-failed","analyzedSha":"4deb7eca8f381f7cbc1f9d15515a9ab8f8009053","analyzedAt":"2026-08-29T09:24:13.446Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}