{"record":{"id":"4993e33c771b3258","repo":"decolua/9router","slug":"callbackparams-error-description-callbackpara","errorCode":null,"errorMessage":"${callbackParams.error_description || callbackParams.error}","messagePattern":"\\$\\{callbackParams\\.error_description \\|\\| callbackParams\\.error\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/oauth/services/antigravity.js","lineNumber":274,"sourceCode":"\n      await new Promise((resolve, reject) => {\n        const timeout = setTimeout(() => {\n          reject(new Error(\"Authentication timeout (5 minutes)\"));\n        }, 300000);\n\n        const checkInterval = setInterval(() => {\n          if (callbackParams) {\n            clearInterval(checkInterval);\n            clearTimeout(timeout);\n            resolve();\n          }\n        }, 100);\n      });\n\n      close();\n\n      if (callbackParams.error) {\n        throw new Error(callbackParams.error_description || callbackParams.error);\n      }\n\n      if (!callbackParams.code) {\n        throw new Error(\"No authorization code received\");\n      }\n\n      spinner.start(\"Exchanging code for tokens...\");\n\n      // Exchange code for tokens\n      const tokens = await this.exchangeCode(callbackParams.code, redirectUri);\n\n      spinner.text = \"Fetching user info...\";\n\n      // Get user info\n      const userInfo = await this.getUserInfo(tokens.access_token);\n\n      spinner.text = \"Loading Code Assist configuration...\";\n","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/services/antigravity.js#L256-L292","documentation":"Thrown by AntigravityService.connect when the OAuth provider redirected back to the local callback server with an `error` query parameter instead of an authorization `code`. The message prefers the OAuth-standard `error_description` and falls back to the bare `error` code (e.g. access_denied). This means Google explicitly refused or aborted the authorization.","triggerScenarios":"User clicks 'Cancel'/'Deny' on the Google consent screen; Google redirects with error=access_denied (scopes rejected or admin policy); redirect_uri mismatch produces error=redirect_uri_mismatch; invalid/expired request produces error=invalid_request.","commonSituations":"Workspace admins blocking third-party app access (Google Workspace 'unconfigured app' block); user closing the consent tab after Google already redirected with an error; client_id's authorized redirect URIs changed in Google Cloud Console.","solutions":["Read error_description in the message to see Google's exact refusal reason","If access_denied: allow the app under Google Account → Security → Third-party access, or have a Workspace admin whitelist it","If redirect_uri_mismatch: add the exact localhost callback URL shown in the CLI to the OAuth client's authorized redirect URIs in Google Cloud Console","Just re-run connect and complete the consent screen without cancelling"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// before opening the browser, verify the OAuth client config\nif (!CLIENT_ID) throw new Error('Missing OAuth client_id — check antigravity config');\nconsole.log('If the browser shows an error, note error_description before closing the tab');","typeGuard":"function isOAuthError(params) { return params != null && typeof params.error === 'string' && params.error.length > 0; }","tryCatchPattern":"try {\n  await service.connect();\n} catch (e) {\n  if (e.message === 'access_denied') {\n    console.error('Consent denied. Allow the app in Google Account → Security → Third-party access.');\n  } else if (e.message.includes('redirect_uri_mismatch')) {\n    console.error('Add the CLI callback URL to authorized redirect URIs in Google Cloud Console.');\n  } else throw e;\n}","preventionTips":["Never cancel the Google consent screen — click Allow","Pre-whitelist the app in Google Workspace admin settings for org accounts","Keep authorized redirect URIs in Google Cloud Console matching the CLI's callback URL","Read error_description in the message — it names Google's exact refusal code"],"tags":["oauth","consent-denied","google-cloud","redirect"],"backgroundTag":"oauth-access-denied","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}