{"record":{"id":"7f4aee2e28c6c617","repo":"redis/node-redis","slug":"msal-client-id-and-msal-tenant-id-environment-vari-7f4aee","errorCode":null,"errorMessage":"MSAL_CLIENT_ID and MSAL_TENANT_ID environment variables must be set","messagePattern":"MSAL_CLIENT_ID and MSAL_TENANT_ID environment variables must be set","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/entraid/samples/interactive-browser/index.ts","lineNumber":30,"sourceCode":"\nconst app = express();\n\nconst sessionConfig = {\n  secret: process.env.SESSION_SECRET,\n  resave: false,\n  saveUninitialized: false,\n  cookie: {\n    secure: process.env.NODE_ENV === 'production', // Only use secure in production\n    httpOnly: true,\n    sameSite: 'lax',\n    maxAge: 3600000 // 1 hour\n  }\n} as const;\n\napp.use(session(sessionConfig));\n\nif (!process.env.MSAL_CLIENT_ID || !process.env.MSAL_TENANT_ID) {\n  throw new Error('MSAL_CLIENT_ID and MSAL_TENANT_ID environment variables must be set');\n}\n\n\napp.get('/login', async (req: Request, res: Response) => {\n  try {\n    // Create an instance of InteractiveBrowserCredential\n    const credential = new InteractiveBrowserCredential({\n      clientId: process.env.MSAL_CLIENT_ID!,\n      tenantId: process.env.MSAL_TENANT_ID!,\n      loginStyle: 'popup',\n      redirectUri: 'http://localhost:3000/redirect'\n    });\n\n    // Create Redis client using the EntraID credentials provider\n    const entraidCredentialsProvider = EntraIdCredentialsProviderFactory.createForDefaultAzureCredential({\n      credential,\n      scopes: ['user.read'],\n      tokenManagerConfig: DEFAULT_TOKEN_MANAGER_CONFIG","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/redis/node-redis/blob/90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58/packages/entraid/samples/interactive-browser/index.ts#L12-L48","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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","Export them in the shell before launching: export MSAL_CLIENT_ID=<client-id> && export MSAL_TENANT_ID=<tenant-id>","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"],"exampleFix":"// before — missing vars, process exits on import\n// (no .env, no shell exports)\n\n// after — packages/entraid/.env\n//   MSAL_CLIENT_ID=11111111-2222-3333-4444-555555555555\n//   MSAL_TENANT_ID=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\n//   SESSION_SECRET=any-long-random-string","handlingStrategy":"validation","validationCode":"function assertEntraIdEnv(): void {\n  const missing: string[] = [];\n  if (!process.env.MSAL_CLIENT_ID) missing.push('MSAL_CLIENT_ID');\n  if (!process.env.MSAL_TENANT_ID) missing.push('MSAL_TENANT_ID');\n  if (missing.length) {\n    throw new Error(`Missing required env vars: ${missing.join(', ')}`);\n  }\n}\n// call before app.listen\nassertEntraIdEnv();","typeGuard":"function hasEntraIdEnv(env: NodeJS.ProcessEnv): env is NodeJS.ProcessEnv & {\n  MSAL_CLIENT_ID: string;\n  MSAL_TENANT_ID: string;\n} {\n  return typeof env.MSAL_CLIENT_ID === 'string' && env.MSAL_CLIENT_ID.length > 0\n      && typeof env.MSAL_TENANT_ID === 'string' && env.MSAL_TENANT_ID.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Commit a .env.example listing MSAL_CLIENT_ID, MSAL_TENANT_ID, and SESSION_SECRET so new contributors copy it","Run the env check in a prelaunch script so failures are obvious before the server binds a port","In CI, fail the job early if the Azure secrets are not injected rather than letting the sample crash on import"],"tags":["entraid","environment-variables","azure","configuration","sample"],"backgroundTag":null,"analyzedSha":"90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58","analyzedAt":"2026-08-11T15:37:21.243Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}