πŸ”§ Error Fixes
Β· 2 min read
Last updated on

T3 Env: Environment Variable Validation Failed


❌ Invalid environment variables: { DATABASE_URL: [ 'Required' ] }

This error means T3 Env (the @t3-oss/env-nextjs or @t3-oss/env-core package) validated your environment variables at build time and found missing or invalid values. The validation uses Zod schemas, so the error message tells you exactly which variable failed and why.

What causes this

T3 Env runs validation when your app starts or builds. If a variable defined in your schema is missing from .env, has the wrong format (e.g., not a valid URL), or isn’t mapped in runtimeEnv, the validation throws.

Common triggers:

  • You added a new variable to the schema but forgot to add it to .env
  • Your .env file isn’t being loaded (wrong location or wrong filename)
  • A NEXT_PUBLIC_ variable isn’t mapped in the runtimeEnv object
  • You’re deploying to CI/CD and the env vars aren’t set there

Fix 1: Add the missing variable to .env

Check the error message β€” it tells you which variable is missing. Add it:

# .env
DATABASE_URL="[postgresql](/blog/what-is-postgresql/)://user:password@localhost:5432/mydb"
NEXT_PUBLIC_APP_URL="http://localhost:3000"

Make sure the .env file is in the project root (next to package.json), not inside src/.

Fix 2: Check your env schema matches reality

Your schema must match what you actually provide. If a variable is optional in practice, mark it as optional in the schema:

import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";

export const env = createEnv({
  server: {
    DATABASE_URL: z.string().url(),
    REDIS_URL: z.string().url().optional(),  // Not always needed
  },
  client: {
    NEXT_PUBLIC_APP_URL: z.string().url(),
  },
  runtimeEnv: {
    DATABASE_URL: process.env.DATABASE_URL,
    REDIS_URL: process.env.REDIS_URL,
    NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
  },
});

Every variable in server and client must also appear in runtimeEnv. Missing a mapping there is a common mistake.

Fix 3: Skip validation in CI/Docker builds

During CI builds or Docker image creation, you often don’t have runtime env vars available. Skip validation for those environments:

export const env = createEnv({
  skipValidation: !!process.env.SKIP_ENV_VALIDATION,
  // ... rest of config
});

Then in your CI pipeline:

SKIP_ENV_VALIDATION=1 npm run build

Fix 4: Check for .env.local overrides

Next.js loads .env.local after .env, and it takes precedence. If you have conflicting values:

# Check which files exist
ls -la .env*

The load order is: .env β†’ .env.local β†’ .env.development β†’ .env.development.local. A variable set to an empty string in a later file will override a valid value from an earlier one.

How to prevent it

  • Keep a .env.example file in version control with all required variables (without real values). New team members copy it to .env and fill in the values.
  • Add SKIP_ENV_VALIDATION=1 to your CI environment so builds don’t fail on missing runtime secrets.
  • Use .optional() or .default() in your Zod schema for variables that aren’t always required.
πŸ“˜