redis/node-redis · error · Error
Invalid token response
Error message
Invalid token response
What it means
`MSALIdentityProvider.requestToken()` calls the injected MSAL `getToken()` and requires the result to have both `accessToken` and `expiresOn`; if either is missing (or the result is null/undefined), it throws 'Invalid token response' rather than handing an incomplete token downstream. The subsequent `ttlMs` math (`expiresOn.getTime()`) would also throw on a non-Date, so the guard prevents that.
Solutions
- Verify MSAL configuration (clientId, tenant, authority, scopes, redirect).
- Ensure the credentials/account used for silent acquisition exist and are valid.
- Make the injected `getToken` reject (not resolve empty) on real failures so requestToken surfaces the underlying MSAL error.
- Clear/rebuild the MSAL token cache if corrupted.
Defensive patterns
Strategy: try-catch
Validate before calling
function isValidTokenResult(r: unknown): r is { accessToken: string; expiresOn: Date } {
return !!r && typeof (r as any)?.accessToken === 'string' && (r as any)?.expiresOn instanceof Date;
} Type guard
function isValidTokenResult(r: unknown): r is { accessToken: string; expiresOn: Date } {
return !!r && typeof (r as any)?.accessToken === 'string' && (r as any)?.expiresOn instanceof Date;
} Try / catch
try {
return await provider.requestToken();
} catch (e) {
if (String(e).includes('Invalid token response')) {
// surface underlying MSAL error by retrying interactive acquisition, or rethrow with context
throw new Error('MSAL returned an incomplete token; check scopes/credentials/account', { cause: e });
}
throw e;
} Prevention
- Make the injected getToken reject on real failures so requestToken surfaces the true cause.
- Validate scopes/clientId/tenant and account presence before silent acquisition.
When it happens
Trigger: MSAL `acquireToken*` returning a result lacking `accessToken` or `expiresOn` (null/undefined or a Partial), passed into the provider. Happens on silent-acquire failures that resolve instead of reject, or malformed cached results.
Common situations: Wrong/missing scopes; invalid client credentials; MSAL token cache corruption; account not present for silent acquisition; misconfigured `getToken` callback.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- MSAL_CLIENT_ID and MSAL_TENANT_ID environment variables…
- MSAL_CLIENT_ID and MSAL_TENANT_ID environment variables…
- expirationRefreshRatio must be greater or equal to 0
- expirationRefreshRatio must be less than or equal to 1
- Invalid authority configuration
AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11).
Data as JSON: /api/errors/5a550ba95e753416.
Report an issue: GitHub.
Appendix: source
Thrown at packages/entraid/lib/msal-identity-provider.ts:17
import {
AuthenticationResult
} from '@azure/msal-node';
import { IdentityProvider, TokenResponse } from '@redis/client/dist/lib/authx';
export class MSALIdentityProvider implements IdentityProvider<AuthenticationResult> {
private readonly getToken: () => Promise<AuthenticationResult>;
constructor(getToken: () => Promise<AuthenticationResult>) {
this.getToken = getToken;
}
async requestToken(): Promise<TokenResponse<AuthenticationResult>> {
const result = await this.getToken();
if (!result?.accessToken || !result?.expiresOn) {
throw new Error('Invalid token response');
}
return {
token: result,
ttlMs: result.expiresOn.getTime() - Date.now()
};
}
}
View on GitHub (pinned to 90fd0652bc)