dotnet/aspnetcore · error · Error
Failed to retrieve token, no account found.
Error message
Failed to retrieve token, no account found.
What it means
In the MSAL-backed Blazor WebAssembly authentication service, getTokenCore attempts to acquire an access token silently for the currently signed-in account. If getAccount() returns no account (the user is not signed in / their session was cleared), there is no account to pass to MSAL's acquireTokenSilent, so the service throws. This indicates an authentication-state mismatch: the code reached token acquisition without a signed-in account.
Solutions
- Guard token requests behind a signed-in check; trigger an interactive login (loginPopup/loginRedirect) when no account exists.
- Handle the thrown error by redirecting the user to authentication, then retrying the token request.
- Verify MSAL cache storage (localStorage/sessionStorage) is not blocked by browser privacy settings.
- Ensure the auth flow fully completes (await AuthenticationService) before requesting tokens.
Example fix
// before
const token = await authService.getAccessToken(opts);
// after
const status = await authService.getAccessToken(opts);
if (status.status === 'requiresRedirect') {
await authService.signIn(returnUrl);
return;
}
// and in MSAL config, fall back to interactive when silent fails:
try { return await msal.acquireTokenSilent(req); }
catch { return await msal.acquireTokenPopup(req); } Defensive patterns
Strategy: try-catch
Validate before calling
// Before requesting a token, check for an account
const accounts = msalInstance.getAllAccounts();
if (accounts.length === 0) {
// trigger interactive sign-in instead of acquiring silently
await msalInstance.loginRedirect(loginRequest);
return;
} Type guard
function hasAccount(accounts: any[]): boolean {
return Array.isArray(accounts) && accounts.length > 0;
} Try / catch
try {
return await authService.getTokenCore(scopes);
} catch (e) {
if (/no account found/i.test((e as Error).message)) {
await msalInstance.loginPopup(loginRequest);
return await authService.getTokenCore(scopes);
}
throw e;
} Prevention
- Gate token requests behind a signed-in check.
- Fall back to interactive sign-in when no account exists.
- Verify MSAL cache storage is not blocked by browser privacy settings.
- Complete the auth flow (await it) before requesting tokens.
When it happens
Trigger: Thrown at line 191 when this.getAccount() returns falsy inside getTokenCore, before constructing the silent token request. Triggered by an interactive token request when MSAL has no account in cache.
Common situations: The user's MSAL session expired or was cleared (cache eviction, browser storage wipe); calling token acquisition before login completes; redirect-based auth where the post-redirect account population race lost; same-site/cookie policies blocking the MSAL cache; the user manually signed out but the app still requested a token.
Related errors
- Scopes not granted.
- Could not load settings from
- Authorization requires a cascading parameter of type Task
- Cannot refresh authentication before the connection is…
- The authorization data specifies an authentication scheme…
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/cfac5b69bca9a741.
Report an issue: GitHub.
Appendix: source
Thrown at src/Components/WebAssembly/Authentication.Msal/src/Interop/AuthenticationService.ts:191
async getAccessToken(request?: AccessTokenRequestOptions): Promise<AccessTokenResult> {
try {
this.trace('getAccessToken', request);
const newToken = await this.getTokenCore(request?.scopes);
return {
status: AccessTokenResultStatus.Success,
token: newToken
};
} catch (e) {
return {
status: AccessTokenResultStatus.RequiresRedirect
};
}
}
async getTokenCore(scopes?: string[]): Promise<AccessToken | undefined> {
const account = this.getAccount();
if (!account) {
throw new Error('Failed to retrieve token, no account found.');
}
const silentRequest = {
redirectUri: this._settings.auth?.redirectUri,
account: account,
scopes: scopes || this._settings.defaultAccessTokenScopes
};
this.debug(`Provisioning a token silently for scopes '${silentRequest.scopes}'`)
this.trace('_msalApplication.acquireTokenSilent', silentRequest);
const response = await this._msalApplication.acquireTokenSilent(silentRequest);
this.trace('_msalApplication.acquireTokenSilent-response', response);
if (response.scopes.length === 0 || response.accessToken === '') {
throw new Error('Scopes not granted.');
}
const result = {View on GitHub (pinned to 3600ca084e)