{"record":{"id":"c985d052e1c40658","repo":"google-gemini/gemini-cli","slug":"user-cancelled-account-validation","errorCode":null,"errorMessage":"User cancelled account validation","messagePattern":"User cancelled account validation","errorType":"exception","errorClass":"ValidationCancelledError","httpStatus":null,"severity":"warning","filePath":"packages/core/src/code_assist/setup.ts","lineNumber":200,"sourceCode":"      },\n    });\n\n    try {\n      validateLoadCodeAssistResponse(loadRes);\n      break;\n    } catch (e) {\n      if (e instanceof ValidationRequiredError && validationHandler) {\n        const intent = await validationHandler(\n          e.validationLink,\n          e.validationDescription,\n        );\n        if (intent === 'verify') {\n          continue;\n        }\n        if (intent === 'change_auth') {\n          throw new ChangeAuthRequestedError();\n        }\n        throw new ValidationCancelledError();\n      }\n      throw e;\n    }\n  }\n\n  if (loadRes.currentTier) {\n    if (!loadRes.paidTier?.id && !loadRes.currentTier.id) {\n      debugLogger.warn(\n        'Warning: Code Assist API did not return a user tier ID. Defaulting to STANDARD tier.',\n      );\n    }\n\n    if (!loadRes.cloudaicompanionProject) {\n      if (projectId) {\n        return {\n          projectId,\n          userTier:\n            loadRes.paidTier?.id ??","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/google-gemini/gemini-cli/blob/5024443c7217464a66e98f80d73172a26440bd8f/packages/core/src/code_assist/setup.ts#L182-L218","documentation":"ValidationCancelledError is thrown when the user dismisses the account-validation prompt without choosing 'verify' or 'change_auth'. setupUser treats it as a non-recoverable abort of the onboarding flow. It only fires when a validationHandler is registered and returns a third/unknown intent.","triggerScenarios":"loadCodeAssist raises ValidationRequiredError; validationHandler(link, description) returns undefined/null/''/'cancel' (anything other than 'verify' or 'change_auth') -> line 200 throws.","commonSituations":"User presses Esc/Ctrl-C in the verification prompt; UI returns undefined because the dialog was closed; programmatic caller forgot to map a 'cancel' button to one of the two known intents.","solutions":["If cancellation was intended, surface 'Account validation cancelled' to the user and exit the onboarding step.","If your handler returned undefined by mistake, map the cancel path to a known intent string explicitly.","To retry instead of abort, return 'verify' from the handler after re-showing the prompt."],"exampleFix":"// before\nconst intent = await showPrompt(); // may return undefined\n// after\nconst intent = (await showPrompt()) ?? 'cancel';\nif (intent === 'cancel') { /* tell user, then abort */ }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"import { ValidationCancelledError } from '../code_assist/setup.js';\nfunction isValidationCancelled(e: unknown): e is ValidationCancelledError {\n  return e instanceof ValidationCancelledError;\n}","tryCatchPattern":"try { await setupUser(client, config); }\ncatch (e) {\n  if (e instanceof ValidationCancelledError) { ui.info('Validation cancelled.'); return; }\n  throw e;\n}","preventionTips":["Map every UI dialog outcome to 'verify' or 'change_auth'; reserve a third value only if you handle the cancel.","Show a clear 'cancelled' message rather than a stack trace."],"tags":["auth","user-cancellation","code-assist","typescript"],"backgroundTag":null,"analyzedSha":"5024443c7217464a66e98f80d73172a26440bd8f","analyzedAt":"2026-08-12T06:01:53.711Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}