From 327e82da5d9cbdbdc164a8f804ee60b7dd98c41c Mon Sep 17 00:00:00 2001 From: Charles-Henri ROBICHE Date: Thu, 29 Jan 2026 11:15:09 +0100 Subject: [PATCH] fix(litellm): add error handling in onboarding wizard The AUTH_CHOICE_CANCELLED error was showing to users during onboarding because the applyAuthChoice call in onboarding.ts wasn't wrapped in error handling. This adds the same try-catch loop pattern used in configure.gateway-auth.ts and agents.commands.add.ts to properly handle the cancellation and re-prompt for auth method selection. --- src/wizard/onboarding.ts | 56 ++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/src/wizard/onboarding.ts b/src/wizard/onboarding.ts index 75543ca19..e609831ba 100644 --- a/src/wizard/onboarding.ts +++ b/src/wizard/onboarding.ts @@ -21,6 +21,7 @@ import { promptRemoteGatewayConfig } from "../commands/onboard-remote.js"; import { setupSkills } from "../commands/onboard-skills.js"; import { setupInternalHooks } from "../commands/onboard-hooks.js"; import type { + AuthChoice, GatewayAuthChoice, OnboardMode, OnboardOptions, @@ -354,26 +355,43 @@ export async function runOnboardingWizard( allowKeychainPrompt: false, }); const authChoiceFromPrompt = opts.authChoice === undefined; - const authChoice = - opts.authChoice ?? - (await promptAuthChoiceGrouped({ - prompter, - store: authStore, - includeSkip: true, - })); + let authChoice: AuthChoice; - const authResult = await applyAuthChoice({ - authChoice, - config: nextConfig, - prompter, - runtime, - setDefaultModel: true, - opts: { - tokenProvider: opts.tokenProvider, - token: opts.authChoice === "apiKey" && opts.token ? opts.token : undefined, - }, - }); - nextConfig = authResult.config; + // Loop to allow retrying auth choice if user cancels during configuration + while (true) { + authChoice = + opts.authChoice ?? + (await promptAuthChoiceGrouped({ + prompter, + store: authStore, + includeSkip: true, + })); + + try { + const authResult = await applyAuthChoice({ + authChoice, + config: nextConfig, + prompter, + runtime, + setDefaultModel: true, + opts: { + tokenProvider: opts.tokenProvider, + token: opts.authChoice === "apiKey" && opts.token ? opts.token : undefined, + }, + }); + nextConfig = authResult.config; + break; // Success - exit the loop + } catch (error) { + // If user cancelled to go back to auth selection, loop again + if (error instanceof Error && error.message === "AUTH_CHOICE_CANCELLED") { + // Clear opts.authChoice so we prompt again + opts.authChoice = undefined; + continue; + } + // Re-throw other errors + throw error; + } + } if (authChoiceFromPrompt) { const modelSelection = await promptDefaultModel({