{"record":{"id":"f740134e1673948c","repo":"DayuanJiang/next-ai-draw-io","slug":"at-least-one-of-customapikeyenv-join-en","errorCode":null,"errorMessage":"At least one of [${customApiKeyEnv.join(\", \")}] environment variables is required for ${provider} provider. Please set at least one in your .env.local file.","messagePattern":"At least one of \\[(.+?)\\] environment variables is required for (.+?) provider\\. Please set at least one in your \\.env\\.local file\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/ai-providers.ts","lineNumber":643,"sourceCode":"    }\n\n    return null\n}\n\n/**\n * Validate that required API keys are present for the selected provider\n * @param provider - The provider to validate\n * @param customApiKeyEnv - Optional custom env var name(s) (from ai-models.json apiKeyEnv)\n */\nfunction validateProviderCredentials(\n    provider: ProviderName,\n    customApiKeyEnv?: string | string[],\n): void {\n    // Handle array of env var names - at least one must be set\n    if (Array.isArray(customApiKeyEnv)) {\n        const hasAnyKey = customApiKeyEnv.some((envVar) => process.env[envVar])\n        if (!hasAnyKey) {\n            throw new Error(\n                `At least one of [${customApiKeyEnv.join(\", \")}] environment variables is required for ${provider} provider. ` +\n                    `Please set at least one in your .env.local file.`,\n            )\n        }\n        return\n    }\n\n    // Anthropic accepts ANTHROPIC_AUTH_TOKEN (Bearer auth) as alternative to ANTHROPIC_API_KEY\n    if (provider === \"anthropic\" && !customApiKeyEnv) {\n        const hasCredential = !!(\n            process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN\n        )\n        if (!hasCredential) {\n            throw new Error(\n                `Either ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN environment variable is required for anthropic provider. ` +\n                    `Please set one in your .env.local file.`,\n            )\n        }","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/DayuanJiang/next-ai-draw-io/blob/155ef4f7acd29c9d46fb6fc35c92e6e6955a6ce1/lib/ai-providers.ts#L625-L661","documentation":"validateProviderCredentials supports an array of acceptable env var names; when none is set it throws listing all candidates required by that provider.","triggerScenarios":"Using a custom provider whose configuration lists multiple possible API key env vars (e.g. OPENROUTER_API_KEY / custom keys) with none present in the environment.","commonSituations":"Renamed env vars after config changes, forgetting to restart after editing .env.local, deploying without copying env settings.","solutions":["Set at least one of the env vars listed in the message in .env.local","Restart the dev server / redeploy so the new env is loaded","Fix typos in the variable name so it matches one of the listed options"],"exampleFix":"# before\n# (no key set)\n\n# after\nOPENROUTER_API_KEY=sk-or-...","handlingStrategy":"validation","validationCode":"const hasAny = (vars: string[]) => vars.some((v) => !!process.env[v])\nif (!hasAny(requiredKeyVars)) throw new Error('Missing credentials config')","typeGuard":null,"tryCatchPattern":"try { getAIModel(...) } catch (e) { if ((e as Error).message.includes('environment variables is required')) showEnvSetupGuide(e) }","preventionTips":["Fail fast at boot with a credential checklist for the chosen provider","Restart servers after env edits","Automate .env drift checks in deployment"],"tags":["env-var","provider","credentials","configuration"],"backgroundTag":"missing-env-var","analyzedSha":"155ef4f7acd29c9d46fb6fc35c92e6e6955a6ce1","analyzedAt":"2026-08-27T11:40:38.297Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}