Environment variables seem simple. Key equals value. What could go wrong?
A lot, actually. After years of debugging production outages, we have identified the five most common environment variable mistakes that break deployments. Each one is preventable with the right tooling.
1. Type Mismatches
The number one cause of env-related bugs: treating everything as a string when your code expects something else.
// .env
PORT=3000
// Your code
if (process.env.PORT === 3000) {
// This NEVER runs!
// PORT is "3000" (string), not 3000 (number)
}
This bug is subtle and dangerous. Your app starts fine, passes basic tests, then fails in unexpected ways at runtime.
The fix: Use type validation in your schema. zorath-env supports int, float, bool, url, and enum types that catch mismatches before your code runs:
{
"PORT": {
"type": "int",
"required": true,
"validate": { "min": 1024, "max": 65535 }
}
}
2. Missing Required Variables
You deploy to production. Everything works in staging. Then: crash.
Why? A required environment variable was set in staging but forgotten in production. The app starts, runs for hours, then hits the code path that needs that variable and explodes.
# Staging .env
DATABASE_URL=postgres://staging-db/app
REDIS_URL=redis://staging-redis:6379
FEATURE_FLAG_API_KEY=sk_test_xxx
# Production .env
DATABASE_URL=postgres://prod-db/app
REDIS_URL=redis://prod-redis:6379
# Oops, forgot FEATURE_FLAG_API_KEY
The fix: Define all required variables in your env.schema.json and run validation at startup. The zenv check command returns exit code 1 if any required variable is missing, failing your deployment fast:
$ zenv check
zenv check failed:
- FEATURE_FLAG_API_KEY: missing (required)
3. Typos in Variable Names
This one hurts:
# .env
DATABSE_URL=postgres://localhost/mydb # Typo: DATABSE instead of DATABASE
Your code references DATABASE_URL. It gets undefined. Your app connects to... nothing. Or worse, it falls back to a hardcoded default and connects to the wrong database.
The fix: zorath-env validates in both directions. Variables in your .env that are not in the schema get flagged as unknown. Variables in your schema missing from .env get flagged as missing:
$ zenv check
zenv check failed:
- DATABASE_URL: missing (required)
- DATABSE_URL: not in schema (unknown key)
The unknown key warning catches the typo immediately.
4. Inconsistent Values Across Environments
Development uses DEBUG=true. Staging uses DEBUG=1. Production uses DEBUG=yes.
All three are "truthy" in different ways, but do they all work the same in your code?
// This only works for DEBUG=true
if (process.env.DEBUG === "true") {
enableDebugMode();
}
// This works for DEBUG=1, but not DEBUG=true
if (parseInt(process.env.DEBUG)) {
enableDebugMode();
}
The fix: Use the bool type in your schema. zorath-env normalizes true, false, 1, 0, yes, and no to consistent boolean semantics:
{
"DEBUG": {
"type": "bool",
"default": false
}
}
For limited choices, use enum validation:
{
"LOG_LEVEL": {
"type": "enum",
"values": ["debug", "info", "warn", "error"],
"default": "info"
}
}
5. Secrets in Version Control
We have all seen it. Someone commits .env to git. Secrets exposed. API keys leaked. A very bad day.
Even if you add .env to .gitignore, there is no enforcement. Nothing stops a developer from force-adding it or committing a .env.production file by accident.
The fix: Multiple layers of defense:
- Use
.env.exampleas documentation - Commit a template without real values - Generate schemas with zenv init - Create
env.schema.jsonfrom your example file - Add pre-commit hooks - Block
.envfiles from being committed - Use secret management - HashiCorp Vault, AWS Secrets Manager, or similar for production
Here is a simple pre-commit hook from our CI/CD integration guide:
#!/usr/bin/env bash
set -e
# Block .env files
if git diff --cached --name-only | grep -qE '^\.env'; then
echo "ERROR: Attempting to commit .env file"
exit 1
fi
# Validate schema
if [ -f "env.schema.json" ]; then
zenv check || exit 1
fi
Prevention Beats Debugging
Every one of these bugs is preventable. Schema-based validation catches them in development, in CI, before they ever reach production.
That is why we built zorath-env. One command validates your entire environment configuration:
# Install once
cargo install zorath-env
# Validate anywhere
zenv check
The tool is open source, runs entirely locally (no data sent anywhere), and works with any tech stack. Your schema becomes the source of truth for environment configuration.
Ready to stop debugging production config issues? Check out our getting started guide or explore the schema reference to learn more.