dotenv Troubleshooting Common Issues Undefined Variables and Loading Problems
Learn how to troubleshoot common dotenv issues in Node.js undefined variables, loading order problems, path issues, and environment-specific .env files.
dotenv Troubleshooting Common Issues
This guide covers the most common dotenv problems and their solutions.
1. process.env.VARIABLE is undefined
Symptom: process.env.JWT_SECRET returns undefined.
Causes and Solutions:
// Cause 1: dotenv not loaded // Solution: Load at the very top of your entry file require("dotenv").config(); // Must be first const express = require("express"); // Cause 2: Variable not in .env file // Check .env: // JWT_SECRET=your_secret_here // Cause 3: Typo in variable name // .env has JWT_SECRET but code uses JWT_TOKEN console.log(process.env.JWT_SECRET); // not JWT_TOKEN // Cause 4: .env file not in the right location // dotenv looks for .env in process.cwd() // Check: console.log(require("path").resolve(".env"));
2. dotenv Not Loading Before Other Modules
Symptom: Variables are undefined in imported modules.
Solution: Load dotenv before any imports that use env vars:
// WRONG config module loads before dotenv const config = require("./config"); // Uses process.env but dotenv not loaded yet! require("dotenv").config(); // Too late! // RIGHT dotenv first require("dotenv").config(); const config = require("./config"); // Now process.env is populated
Or use a separate entry file:
// load-env.js require("dotenv").config(); require("./server"); // server.js const express = require("express"); // process.env is available
3. .env File Path Issues
Symptom: dotenv can't find .env file.
Solutions:
// Default: looks in process.cwd() require("dotenv").config(); // Custom path require("dotenv").config({ path: "/custom/path/to/.env" }); // Relative to the file const path = require("path"); require("dotenv").config({ path: path.join(__dirname, "../.env") }); // Debug mode to see what's happening require("dotenv").config({ debug: true });
4. Environment-Specific .env Not Loading
Symptom: .env.production not loaded on production server.
Solutions:
// Use dotenv-flow for automatic environment file loading require("dotenv-flow").config(); // Or specify the path manually const env = process.env.NODE_ENV || "development"; require("dotenv").config({ path: `.env.${env}` }); // Ensure NODE_ENV is set before loading // On EC2: export NODE_ENV=production before starting the app // Or in PM2 ecosystem file: env: { NODE_ENV: "production" }
5. Variables with Spaces or Special Characters
Symptom: Variable value is truncated or includes unwanted characters.
Solutions:
# .env # WRONG spaces break the value JWT_SECRET=my secret with spaces # RIGHT use quotes JWT_SECRET="my secret with spaces" JWT_SECRET='my secret with spaces' # Multi-line values PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA... -----END RSA PRIVATE KEY-----" # Values with # (not comments) API_KEY="abc#123" # This # is part of the value, not a comment
6. Comments in .env File
# This is a comment (entire line) PORT=3000 # This is also a comment (after the value) # WRONG # inside value without quotes API_KEY=abc#123 # dotenv may interpret #123 as a comment # RIGHT use quotes API_KEY="abc#123"
7. .env File Encoding Issues
Symptom: Variables have weird characters or BOM prefix.
Solutions:
# Ensure .env is saved as UTF-8 without BOM # In VS Code: bottom right corner → UTF-8 → Save with Encoding → UTF-8 # Check for BOM file .env # If it says "UTF-8 Unicode (with BOM) text", re-save without BOM
8. Overriding Env Vars in Production
Symptom: .env values are used instead of system environment variables.
Solutions:
// dotenv does NOT override existing environment variables by default // If MONGODB_URI is set in the system, .env is ignored for that variable // To force override (not recommended in production): require("dotenv").config({ override: true }); // In production, set env vars in the system (not .env): // export MONGODB_URI=mongodb+srv://... // Or in PM2: env: { MONGODB_URI: "..." }
9. Debugging dotenv
// Enable debug mode to see what dotenv is doing require("dotenv").config({ debug: true }); // Output: // [dotenv][DEBUG] loading .env // [dotenv][DEBUG] port=3000 // [dotenv][DEBUG] jwt_secret=abc123 // Log all environment variables (be careful includes secrets!) // console.log(process.env);
10. dotenv in Docker
Symptom: .env not loaded in Docker container.
Solutions:
# Dockerfile COPY .env /app/.env # Or pass at runtime
# Pass env vars at runtime docker run -e MONGODB_URI=$MONGODB_URI -e JWT_SECRET=$JWT_SECRET my-app # Or use --env-file docker run --env-file .env.production my-app
The Takeaway
Common dotenv issues include: undefined variables (check loading order, typos, file path), loading before other modules (load dotenv first), path issues (use path.join(__dirname, ...)), environment-specific files (use dotenv-flow or specify path), spaces and special characters (use quotes), comments (use quotes for values with #), encoding (save as UTF-8 without BOM), and Docker (use -e or --env-file). Use debug: true to troubleshoot.
Common causes: dotenv not loaded (add require('dotenv').config() at the top), variable not in .env file, typo in variable name, or .env file not in the right location (dotenv looks in process.cwd()). Use debug: true to see what dotenv is loading.
dotenv must be loaded before any module that uses process.env. If a config module is imported before require('dotenv').config(), the variables will be undefined. Load dotenv at the very top of your entry file (server.js or app.js).
Use quotes: JWT_SECRET="my secret with spaces". For multi-line values (like private keys), use double quotes. For values with # (which dotenv interprets as comments), wrap in quotes: API_KEY="abc#123".
Use dotenv-flow (require('dotenv-flow').config()) which automatically loads .env, .env.local, .env.${NODE_ENV}, and .env.${NODE_ENV}.local. Or specify the path manually: require('dotenv').config({ path: '.env.production' }). Ensure NODE_ENV is set before loading.
Enable debug mode: require('dotenv').config({ debug: true }). This logs every variable that dotenv loads, the file path it's reading from, and any parsing issues. Also check console.log(process.env) to see all loaded variables (be careful not to log secrets in production).
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

