redis/node-redis · error · Error

MSAL_CLIENT_ID and MSAL_TENANT_ID environment variables…

Error message

MSAL_CLIENT_ID and MSAL_TENANT_ID environment variables must be set

What it means

Thrown synchronously at module load by the interactive-browser sample app when either MSAL_CLIENT_ID or MSAL_TENANT_ID is absent from the environment. Both values are required to construct an InteractiveBrowserCredential against a Microsoft Entra ID (Azure AD) app registration. The app calls dotenv.config() earlier in the same file, so values may come from a .env file in the working directory or from the process environment.

Solutions

  1. Create a .env file in packages/entraid (or the repo root, depending on where you launch) with MSAL_CLIENT_ID and MSAL_TENANT_ID copied from your Azure app registration
  2. Export them in the shell before launching: export MSAL_CLIENT_ID=<client-id> && export MSAL_TENANT_ID=<tenant-id>
  3. Register an application in the Azure Entra ID portal to obtain a client (application) ID and note the directory (tenant) ID if you do not yet have them

Example fix

// before — missing vars, process exits on import
// (no .env, no shell exports)

// after — packages/entraid/.env
//   MSAL_CLIENT_ID=11111111-2222-3333-4444-555555555555
//   MSAL_TENANT_ID=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
//   SESSION_SECRET=any-long-random-string
Defensive patterns

Strategy: validation

Validate before calling

function assertEntraIdEnv(): void {
  const missing: string[] = [];
  if (!process.env.MSAL_CLIENT_ID) missing.push('MSAL_CLIENT_ID');
  if (!process.env.MSAL_TENANT_ID) missing.push('MSAL_TENANT_ID');
  if (missing.length) {
    throw new Error(`Missing required env vars: ${missing.join(', ')}`);
  }
}
// call before app.listen
assertEntraIdEnv();

Type guard

function hasEntraIdEnv(env: NodeJS.ProcessEnv): env is NodeJS.ProcessEnv & {
  MSAL_CLIENT_ID: string;
  MSAL_TENANT_ID: string;
} {
  return typeof env.MSAL_CLIENT_ID === 'string' && env.MSAL_CLIENT_ID.length > 0
      && typeof env.MSAL_TENANT_ID === 'string' && env.MSAL_TENANT_ID.length > 0;
}

Prevention

When it happens

Trigger: Running the sample (e.g. `npx tsx packages/entraid/samples/interactive-browser/index.ts` or the built JS) without MSAL_CLIENT_ID/MSAL_TENANT_ID set in the shell or in a .env file resolvable from the process working directory.

Common situations: Fresh clone with no .env file copied from .env.example; CI pipeline that forgot to inject the Azure secrets; running from a different working directory so dotenv cannot locate .env; app registration not yet created in Entra ID.

Related errors


AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11). Data as JSON: /api/errors/7f4aee2e28c6c617. Report an issue: GitHub.

Appendix: source

Thrown at packages/entraid/samples/interactive-browser/index.ts:30

const app = express();

const sessionConfig = {
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: process.env.NODE_ENV === 'production', // Only use secure in production
    httpOnly: true,
    sameSite: 'lax',
    maxAge: 3600000 // 1 hour
  }
} as const;

app.use(session(sessionConfig));

if (!process.env.MSAL_CLIENT_ID || !process.env.MSAL_TENANT_ID) {
  throw new Error('MSAL_CLIENT_ID and MSAL_TENANT_ID environment variables must be set');
}


app.get('/login', async (req: Request, res: Response) => {
  try {
    // Create an instance of InteractiveBrowserCredential
    const credential = new InteractiveBrowserCredential({
      clientId: process.env.MSAL_CLIENT_ID!,
      tenantId: process.env.MSAL_TENANT_ID!,
      loginStyle: 'popup',
      redirectUri: 'http://localhost:3000/redirect'
    });

    // Create Redis client using the EntraID credentials provider
    const entraidCredentialsProvider = EntraIdCredentialsProviderFactory.createForDefaultAzureCredential({
      credential,
      scopes: ['user.read'],
      tokenManagerConfig: DEFAULT_TOKEN_MANAGER_CONFIG

View on GitHub (pinned to 90fd0652bc)