{"record":{"id":"0bd5f815b5514266","repo":"decolua/9router","slug":"no-authorization-code-found-in-url","errorCode":null,"errorMessage":"No authorization code found in URL","messagePattern":"No authorization code found in URL","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/shared/components/KiroSocialOAuthModal.js","lineNumber":82,"sourceCode":"      // Parse callback URL - can be either kiro:// or http://localhost format\n      let url;\n      try {\n        url = new URL(callbackUrl);\n      } catch (e) {\n        // If URL parsing fails, might be malformed\n        throw new Error(\"Invalid callback URL format\");\n      }\n\n      const code = url.searchParams.get(\"code\");\n      const state = url.searchParams.get(\"state\");\n      const errorParam = url.searchParams.get(\"error\");\n\n      if (errorParam) {\n        throw new Error(url.searchParams.get(\"error_description\") || errorParam);\n      }\n\n      if (!code) {\n        throw new Error(\"No authorization code found in URL\");\n      }\n\n      // Exchange code for tokens\n      const res = await fetch(\"/api/oauth/kiro/social-exchange\", {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify({\n          code,\n          codeVerifier: authData.codeVerifier,\n          provider,\n        }),\n      });\n\n      const data = await res.json();\n      if (!res.ok) throw new Error(data.error);\n\n      setStep(\"success\");\n      onSuccess?.();","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/shared/components/KiroSocialOAuthModal.js#L64-L100","documentation":"handleManualSubmit throws this when the parsed callback URL has no `code` query parameter and no `error` param. A successful OAuth redirect must carry `?code=...` (plus `state`); without it the modal cannot proceed to POST /api/oauth/kiro/social-exchange to swap the code for tokens.","triggerScenarios":"User pastes a callback URL that parses but lacks `code` — e.g. they pasted the base callback/redirect URL itself, a URL that only has `state`, a logout or error page URL, or the provider put the code in the URL fragment (#code=...) instead of the query string.","commonSituations":"Copying the redirect_uri from app config instead of the actual redirected address; pasting the URL before completing the consent redirect; fragment-based responses (implicit flow) that this code-exchange flow doesn't support.","solutions":["Re-do the authorization and copy the final browser URL after the provider redirects — it must contain ?code=...","Verify you copied the full URL including query string (some browsers/apps strip it on copy).","If the code appears after '#' instead of '?', the provider used the implicit flow — this modal requires the authorization-code flow; fix the provider/app config.","Confirm `state` also matches what initAuth issued; a state-only URL means the redirect never completed."],"exampleFix":"// before\nif (!code) {\n  throw new Error(\"No authorization code found in URL\");\n}\n// after\nif (!code) {\n  const hashParams = new URLSearchParams(url.hash.replace(/^#/, \"\"));\n  throw new Error(`No authorization code found in URL (params: ${[...url.searchParams.keys(), ...hashParams.keys()].join(\", \") || \"none\"})`);\n}","handlingStrategy":"validation","validationCode":"function callbackHasCode(s) {\n  try {\n    const u = new URL(String(s).trim());\n    const q = u.searchParams.get(\"code\");\n    const h = new URLSearchParams(u.hash.replace(/^#/, \"\")).get(\"code\"); // implicit-flow fallback\n    return Boolean(q || h);\n  } catch { return false; }\n}\nif (!callbackHasCode(callbackUrl)) {\n  setError(\"URL must contain ?code= — re-copy the address after the provider redirects back\");\n  return;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Copy the URL only after the provider's final redirect completes.","Ensure the full query string survives the copy (some apps strip it).","Use the authorization-code flow; fragment (#code=...) responses aren't supported.","Don't paste the configured redirect_uri itself — paste the actual redirected address."],"tags":["oauth","validation","kiro","callback"],"backgroundTag":"missing-oauth-code","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}