{"record":{"id":"3e5f0cea5824ed13","repo":"can1357/oh-my-pi","slug":"ineligibility-reasonmessage-validation","errorCode":null,"errorMessage":"${ineligibility.reasonMessage}${validation}","messagePattern":"\\$\\{ineligibility\\.reasonMessage\\}\\$\\{validation\\}","errorType":"exception","errorClass":"AIError.OAuthError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/registry/oauth/google-antigravity.ts","lineNumber":145,"sourceCode":"}\n\nfunction getFreeTierIneligibility(\n\tpayload: LoadCodeAssistResponse,\n): { reasonMessage: string; validationUrl: string | undefined } | undefined {\n\tconst tier = payload.ineligibleTiers?.find(candidate => candidate.tierId === FREE_TIER_ID);\n\tif (!tier?.reasonMessage) return undefined;\n\treturn {\n\t\treasonMessage: tier.reasonMessage,\n\t\tvalidationUrl: tier.validationUrl && tier.validationUrl.length > 0 ? tier.validationUrl : undefined,\n\t};\n}\n\nfunction assertFreeTierEligible(payload: LoadCodeAssistResponse): void {\n\tif (isFreeTierAllowed(payload)) return;\n\tconst ineligibility = getFreeTierIneligibility(payload);\n\tif (!ineligibility) return;\n\tconst validation = ineligibility.validationUrl ? `\\n${ineligibility.validationUrl}` : \"\";\n\tthrow new AIError.OAuthError(`${ineligibility.reasonMessage}${validation}`, {\n\t\tkind: \"provisioning\",\n\t\tprovider: PROVIDER,\n\t});\n}\n\nasync function requestCloudCodeAssist({\n\tlabel,\n\turl,\n\tmethod,\n\theaders,\n\tbody,\n\tsignal,\n\ttimeoutMs,\n}: CloudCodeRequest): Promise<unknown> {\n\tthrowIfLoginCancelled(signal);\n\tconst init: RequestInit = body === undefined ? { method, headers } : { method, headers, body };\n\tconst response = await oauthFetch(url, init, { provider: PROVIDER, signal, timeoutMs });\n\tif (response.status !== 200) {","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/registry/oauth/google-antigravity.ts#L127-L163","documentation":"assertFreeTierEligible runs after loadCodeAssist during Antigravity login. If the free tier is not in allowedTiers but appears in ineligibleTiers with a reasonMessage, this provisioning OAuthError surfaces Google's own ineligibility message (plus an optional validation URL appended on a new line). The Google account cannot use the Antigravity free tier, so the login aborts before onboarding.","triggerScenarios":"loadCodeAssist returns a payload where allowedTiers lacks the 'free-tier' id and ineligibleTiers contains a 'free-tier' entry with tierId 'free-tier' and a non-empty reasonMessage; assertFreeTierEligible then throws reasonMessage (+ validationUrl).","commonSituations":"Google Workspace-managed accounts where the admin disabled Cloud Code/Antigravity; accounts already on a paid tier or with billing configs blocking the free tier; region restrictions; accounts flagged by Google requiring additional validation (the validationUrl points to the fix, e.g. accepting terms or verifying identity).","solutions":["Open the validationUrl printed in the error message and complete whatever Google requires (terms acceptance, identity/billing verification).","Check with your Google Cloud/Workspace administrator that Cloud AI Companion / Gemini Code Assist is enabled for your account.","Verify your account's region is supported for the Antigravity free tier.","Try a different Google account that is eligible for the free tier.","If you believe eligibility is wrong, re-run login after fixing account settings to refresh loadCodeAssist."],"exampleFix":"// The error itself is not a code bug; resolve the account restriction:\n// error message example:\n// \"Free tier is not available for this account.\\nhttps://codeassist.google.com/validate\"\n// after completing validation at the URL, retry:\nawait loginAntigravity(ctrl); // now passes assertFreeTierEligible","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await loginAntigravity(ctrl);\n} catch (err) {\n  if (err instanceof AIError.OAuthError && err.provider === \"google-antigravity\" && !String(err.message).includes(\"failed to\")) {\n    // Google's own ineligibility message (+ optional validation URL). Surface it verbatim:\n    ui.show_message(\"Antigravity login blocked\", `${err.message}\\nOpen the validation URL above to fix eligibility.`);\n  } else {\n    throw err;\n  }\n}","preventionTips":["Read the reasonMessage/validationUrl in the error — it is Google's own guidance on how to become eligible.","Ensure the Google account is not Workspace-restricted (admin must enable Cloud AI Companion).","Verify the account's region and billing configuration support the free tier before integrating.","Pre-test eligibility with a known-good Google account in CI before enabling the provider."],"tags":["google","oauth","provisioning","account-eligibility","free-tier"],"backgroundTag":"account-ineligible-for-tier","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}