Change:
@IStorageService private readonly storageService: IStorageService, @IKeybindingService keybindingService: IKeybindingService, @ICredentialsService private readonly credentialsService: ICredentialsService, <ins> @ILogService private readonly logService: ILogService </ins> ) { super(MenuId.AccountsContext, action, contextMenuActionsProvider, true, colors, activityHoverOptions, themeService, hoverService, menuService, contextMenuService, contextKeyService, configurationService, environmentService, keybindingService); <ins> this.registerListeners(); this.initialize(); } private registerListeners(): void { this._register(this.authenticationService.onDidRegisterAuthenticationProvider(async (e) => { await this.addAccountsFromProvider(e.id); })); this._register(this.authenticationService.onDidUnregisterAuthenticationProvider((e) => { this.groupedAccounts.delete(e.id); this.problematicProviders.delete(e.id); })); this._register(this.authenticationService.onDidChangeSessions(async e => { const promises = []; for (const changed of e.event.changed) { promises.push(this.addOrUpdateAccount(e.providerId, changed.account)); } for (const added of e.event.added) { promises.push(this.addOrUpdateAccount(e.providerId, added.account)); } const result = await Promise.allSettled(promises); for (const r of result) { if (r.status === 'rejected') { this.logService.error(r.reason); } } for (const removed of e.event.removed) { this.removeAccount(e.providerId, removed.account); } })); } // This function exists to ensure that the accounts are added for auth providers that had already been registered // before the menu was created. private async initialize(): Promise<void> { const providerIds = this.authenticationService.getProviderIds(); const results = await Promise.allSettled(providerIds.map(providerId => this.addAccountsFromProvider(providerId))); // Log any errors that occurred while initializing. We try to be best effort here to show the most amount of accounts for (const result of results) { if (result.status === 'rejected') { this.logService.error(result.reason); } } this.initialized = true; </ins> } <ins> //#region overrides </ins> protected override async resolveMainMenuActions(accountsMenu: IMenu, disposables: DisposableStore): Promise<IAction[]> { await super.resolveMainMenuActions(accountsMenu, disposables); <del> const otherCommands = accountsMenu.getActions(); </del> const providers = this.authenticationService.getProviderIds(); <del> const allSessions = providers.map(async providerId => { try { const sessions = await this.authenticationService.getSessions(providerId); const groupedSessions: { [label: string]: AuthenticationSession[] } = {}; sessions.forEach(session => { if (groupedSessions[session.account.label]) { groupedSessions[session.account.label].push(session); } else { groupedSessions[session.account.label] = [session]; } }); </del> <ins> const otherCommands = accountsMenu.getActions(); let menus: IAction[] = []; </ins> <del> return { providerId, sessions: groupedSessions }; } catch { return { providerId }; </del> <ins> for (const providerId of providers) { if (!this.initialized) { const noAccountsAvailableAction = disposables.add(new Action('noAccountsAvailable', localize('loading', "Loading..."), undefined, false)); menus.push(noAccountsAvailableAction); break; } const providerLabel = this.authenticationService.getLabel(providerId); const accounts = this.groupedAccounts.get(providerId); if (!accounts) { if (this.problematicProviders.has(providerId)) { const providerUnavailableAction = disposables.add(new Action('providerUnavailable', localize('authProviderUnavailable', '{0} is currently unavailable', providerLabel), undefined, false)); menus.push(providerUnavailableAction); // try again in the background so that if the failure was intermittent, we can resolve it on the next showing of the menu try { await this.addAccountsFromProvider(providerId); } catch (e) { this.logService.error(e); } } continue; </ins> } <del> }); const result = await Promise.all(allSessions); let menus: IAction[] = []; const authenticationSession = await getCurrentAuthenticationSessionInfo(this.credentialsService, this.productService); result.forEach(sessionInfo => { const providerDisplayName = this.authenticationService.getLabel(sessionInfo.providerId); if (sessionInfo.sessions) { Object.keys(sessionInfo.sessions).forEach(accountName => { const manageExtensionsAction = disposables.add(new Action(`configureSessions${accountName}`, localize('manageTrustedExtensions', "Manage Trusted Extensions"), '', true, () => { return this.authenticationService.manageTrustedExtensionsForAccount(sessionInfo.providerId, accountName); })); const signOutAction = disposables.add(new Action('signOut', localize('signOut', "Sign Out"), '', true, () => { return this.authenticationService.removeAccountSessions(sessionInfo.providerId, accountName, sessionInfo.sessions[accountName]); })); </del> <ins> for (const account of accounts) { const manageExtensionsAction = disposables.add(new Action(`configureSessions${account.label}`, localize('manageTrustedExtensions', "Manage Trusted Extensions"), undefined, true, () => { return this.authenticationService.manageTrustedExtensionsForAccount(providerId, account.label); })); </ins> <del> const providerSubMenuActions = [manageExtensionsAction]; </del> <ins> const providerSubMenuActions: Action[] = [manageExtensionsAction]; </ins> <del> const hasEmbedderAccountSession = sessionInfo.sessions[accountName].some(session => session.id === (authenticationSession?.id)); if (!hasEmbedderAccountSession || authenticationSession?.canSignOut) { providerSubMenuActions.push(signOutAction); } </del> <ins> if (account.canSignOut) { const signOutAction = disposables.add(new Action('signOut', localize('signOut', "Sign Out"), undefined, true, async () => { const allSessions = await this.authenticationService.getSessions(providerId); const sessionsForAccount = allSessions.filter(s => s.account.id === account.id); return await this.authenticationService.removeAccountSessions(providerId, account.label, sessionsForAccount); })); providerSubMenuActions.push(signOutAction); } </ins> <del> const providerSubMenu = new SubmenuAction('activitybar.submenu', `${accountName} (${providerDisplayName})`, providerSubMenuActions); menus.push(providerSubMenu); }); } else { const providerUnavailableAction = disposables.add(new Action('providerUnavailable', localize('authProviderUnavailable', '{0} is currently unavailable', providerDisplayName))); menus.push(providerUnavailableAction); </del> <ins> const providerSubMenu = new SubmenuAction('activitybar.submenu', `${account.label} (${providerLabel})`, providerSubMenuActions); menus.push(providerSubMenu); </ins> } <del> }); </del> <ins> } </ins> if (providers.length && !menus.length) { const noAccountsAvailableAction = disposables.add(new Action('noAccountsAvailable', localize('noAccounts', "You are not signed in to any accounts"), undefined, false));

Discussion:
Update: reproduces in web + desktop Steps to Reproduce: a Codespace until it is loaded various activity bar items that open menus (gear menu, accounts, main menu, home indicator) = somehow the accounts menu only opens for me after a delay, as if something was resolved when clicking? !
This still reproduces
does this still repro? maybe its imperceptible to me?
Yeah still seems slightly delayed to me, can we not check the code and see if a longer running promise prevents the menu from showing?
looks like we fetch session info every time, so this probably adds some delay. maybe this can be cached and updated separately
Yeah that seems like a reasonable ask since it goes to the extension host and back, today.
This issue has existed since 2 years! But only recently have I encountered this.