{
  "id": "ai-forgets-env-validation",
  "type": "failures",
  "category": "failures",
  "locale": "es",
  "url": "/es/failures/ai-forgets-env-validation",
  "title": "Cómo solucionar que la IA olvide la validación de variables de entorno",
  "description": "Los agentes de IA leen los valores de process.env directamente sin validación, lo que provoca errores silenciosos de undefined y la ausencia de errores de inicio cuando faltan variables de entorno.",
  "tools": [
    "Cursor",
    "Claude Code",
    "Codex",
    "Windsurf"
  ],
  "stack": [
    "Next.js",
    "TypeScript",
    "Cloudflare"
  ],
  "tags": [
    "security",
    "typescript",
    "cloudflare"
  ],
  "difficulty": null,
  "updated": "2026-06-08",
  "markdown": "El agente accede a `process.env.SOME_KEY` directamente, por lo que cuando la variable falta, la aplicación se inicia silenciosamente rota — sin crash, sin advertencia, solo `undefined` fluyendo a través de la lógica de negocio.\n\n## El síntoma\n\nLecturas de `process.env` dispersas por el código base sin esquema, sin seguridad de tipos y sin aserción al inicio.\n\n```ts\n// lib/stripe.ts — WRONG\nimport Stripe from \"stripe\";\n\nexport const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {\n  apiVersion: \"2024-06-20\",\n});\n// If STRIPE_SECRET_KEY is undefined, Stripe SDK accepts it and every\n// charge silently fails at runtime instead of at startup.\n```\n\n## Por qué sucede\n\nEl agente optimiza por brevedad y por alcanzar código funcional rápidamente. La validación de variables de entorno es un boilerplate que no aparece en la mayoría de los ejemplos de entrenamiento, por lo que el modelo lo omite y va directo a la integración.\n\n## Cómo detectarlo\n\n- `process.env.FOO` usado sin una aserción no nula o comprobación de fallback.\n- No hay un archivo de validación `env.ts` / `env.mjs` en el proyecto.\n- El tipo TypeScript de un valor de entorno es `string | undefined` en el punto de uso.\n- La aplicación arranca sin error incluso cuando `.env.local` está vacío.\n\n## Cómo solucionarlo\n\nValida todas las variables de entorno requeridas al inicio usando un esquema Zod para que el proceso falle con un mensaje claro antes de atender una sola petición.\n\n```ts\n// lib/env.ts — CORRECT\nimport { z } from \"zod\";\n\nconst envSchema = z.object({\n  STRIPE_SECRET_KEY: z.string().min(1),\n  DATABASE_URL: z.string().url(),\n  NEXTAUTH_SECRET: z.string().min(32),\n  NODE_ENV: z.enum([\"development\", \"production\", \"test\"]).default(\"development\"),\n});\n\nexport const env = envSchema.parse(process.env);\n//                             ^^^^^ throws at startup if any var is missing\n```\n\n```ts\n// lib/stripe.ts — CORRECT (import validated env)\nimport Stripe from \"stripe\";\nimport { env } from \"@/lib/env\";\n\nexport const stripe = new Stripe(env.STRIPE_SECRET_KEY, {\n  apiVersion: \"2024-06-20\",\n});\n```\n\n```txt\n[ ] Create lib/env.ts with a Zod schema covering every required variable\n[ ] Import env from lib/env everywhere — never use process.env directly\n[ ] Add lib/env.ts to the module graph so it runs at server startup (import in next.config.ts)\n[ ] Document all variables in .env.example with placeholder values\n[ ] Use z.string().url() / z.string().min(n) for format constraints, not just presence\n```\n\n## Prompt de corrección\n\n```txt title=\"Fix Prompt\"\nEvery raw process.env access in this file is unvalidated. Create a lib/env.ts\nmodule that parses and validates all required environment variables with Zod at\nstartup. Replace every process.env.FOO reference in the codebase with the\ntyped env.FOO import. Add a .env.example file listing every variable with a\nplaceholder value and comment.\n```\n\n## Prueba\n\n```bash\n# Find any remaining raw process.env reads outside of lib/env.ts\ngrep -rn \"process\\.env\\.\" --include=\"*.ts\" --include=\"*.tsx\" . \\\n  | grep -v \"lib/env.ts\" \\\n  | grep -v \"next.config\" \\\n  | grep -v \"node_modules\" \\\n  && echo \"FAIL: raw process.env reads found\" || echo \"OK\"\n```"
}