dotenv
>=1.0.0postconditions15functions5last verified2026-06-24coverage score100%Postconditions: what we check
- config · missing-env-fileinfoWhen.env file does not exist or cannot be readReturnsObject with 'error' property containing the Error instanceRequired handlingCaller MAY check result.error after calling config(). config() does NOT throw on missing .env files — it returns { error }. Most callers intentionally ignore the return value because missing .env is expected in production (env vars set via platform). Only check in development/local.costlowin prodsilent failureusers seedegraded performancevisibilitysilent
- config · parse-errorinfoWhen.env file exists but contains a syntax errorReturnsObject with 'error' property containing the parse Error instanceRequired handlingCaller MAY check result.error. config() does NOT throw on parse errors — it returns { error }. Unhandled parse errors silently leave process.env in a partially-populated state.costlowin prodsilent failureusers seedegraded performancevisibilitysilent
- config · vault-invalid-dotenv-keyerrorWhenDOTENV_KEY is set but is malformed (wrong URI format, missing key part, missing environment part, or key is shorter than 64 hex characters)Throws
Error with code 'INVALID_DOTENV_KEY'. Messages include: "Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/...", "Missing key part", "Missing environment part", "It must be 64 characters long (or more)".Required handlingWhen using .env.vault with DOTENV_KEY, callers MUST wrap config() in a try-catch block. In vault mode config() throws (does not return {error}). A malformed key causes an immediate exception that will crash the process if uncaught.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - config · vault-environment-not-founderrorWhenDOTENV_KEY references an environment (e.g. 'production') but the corresponding DOTENV_VAULT_PRODUCTION key is not found in the .env.vault fileThrows
Error with code 'NOT_FOUND_DOTENV_ENVIRONMENT'. Message: "Cannot locate environment DOTENV_VAULT_<ENVIRONMENT> in your .env.vault file."Required handlingWrap config() in try-catch when using vault mode. This error occurs when the vault was built for a different environment than the key references. Common during deployments when DOTENV_KEY from staging is accidentally used in production.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - config · vault-decryption-failederrorWhenDOTENV_KEY is syntactically valid but does not decrypt the vault ciphertext (wrong key for the environment, rotated key no longer matches)Throws
Error with code 'DECRYPTION_FAILED'. Message: "Please check your DOTENV_KEY".Required handlingWrap config() in try-catch when using vault mode. This is the most common vault error in production — it occurs when the DOTENV_KEY env var is stale or belongs to a different environment's vault. Application starts with no secrets loaded.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - config · vault-missing-dataerrorWhenThe .env.vault file exists (detected because DOTENV_KEY is set) but its contents cannot be parsed (empty file, corrupted, wrong format)Throws
Error with code 'MISSING_DATA'. Message: "Cannot parse <vaultPath> for an unknown reason".Required handlingWrap config() in try-catch when using vault mode. A corrupted or empty vault file causes an immediate throw. Secrets are not loaded.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - config · successinfoWhen.env file is found and parsed successfullyReturnsObject with 'parsed' key containing the parsed key-value pairsRequired handlingNo action required — use the returned value as needed.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1]
- configDotenv · configdotenv-file-not-founderrorWhenOne or more paths in options.path do not exist or cannot be readReturnsObject with 'error' property set to the last filesystem error encountered. The 'parsed' key is still present with whatever keys were successfully loaded from other files.Required handlingCaller MUST check result.error. When path is an array, configDotenv() continues loading remaining files on error (lastError tracking) but the final result includes the error from the last failed file. Silently missing .env files are a common misconfiguration in containerized deployments.costmediumin prodsilent failureusers seedegraded performancevisibilitysilentSources[3]
- configDotenv · configdotenv-partial-load-on-multi-pathwarningWhenoptions.path is an array of multiple file paths and some exist while others do notReturnsObject with 'parsed' containing keys from successfully loaded files only. 'error' is set to the last error from any failed file even if other files loaded successfully.Required handlingWhen using multiple paths, callers relying on all files being present MUST validate result.error AND verify all expected keys exist in result.parsed. The presence of result.error does not mean zero keys were loaded.costmediumin prodsilent failureusers seedegraded performancevisibilitysilentSources[3]
- parse · parse-silent-skip-on-malformed-lineswarningWhenInput string contains lines that do not match the KEY=VALUE patternReturnsPlain object containing only the lines that did match. Malformed lines are silently dropped. Return value may be an empty object if no lines match.Required handlingCallers MUST NOT rely on parse() throwing to detect malformed input. Silent partial parsing means the returned object may be missing expected keys without any error signal. Callers that need strict validation must implement their own key-presence checks after calling parse().costlowin prodsilent failureusers seedegraded performancevisibilitysilentSources[3]
- parse · successinfoWheninput is a valid .env-format string or BufferReturnsPlain object with string keys and string valuesRequired handlingNo action required — use the returned value as needed.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4]
- populate · no-override-by-defaultwarningWhena key already exists on the target object and override is not set to trueReturnsExisting value is preserved; parsed value is ignoredRequired handlingCallers that intend to force-update existing values MUST pass { override: true }. Omitting this option causes pre-existing environment variables (e.g., set by the OS or CI) to silently take precedence.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5]
- populate · populate-object-requirederrorWhenThe parsed argument passed to populate() is not an object (e.g. null, string, number)Throws
Error with code 'OBJECT_REQUIRED'. Message: "Please check the processEnv argument being passed to populate".Required handlingCallers that build the parsed input dynamically (e.g. from JSON.parse of untrusted input) MUST validate the input is an object before calling populate(). Passing null or a primitive throws synchronously and bypasses any surrounding error handling that only catches async errors.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - decrypt · decrypt-invalid-key-lengtherrorWhenkeyStr is shorter than 64 hex characters (the last 64 chars are sliced for the AES key; a shorter string produces an invalid 32-byte key)Throws
Error with code 'INVALID_DOTENV_KEY'. Message: "It must be 64 characters long (or more)".Required handlingCallers MUST wrap decrypt() in try-catch. This error indicates the DOTENV_KEY was truncated or corrupted. Attempting decryption with a short key will crash the process.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - decrypt · decrypt-wrong-keyerrorWhenkeyStr is the correct length but does not decrypt the ciphertext (wrong environment key, key rotation mismatch, or ciphertext tampered with)Throws
Error with code 'DECRYPTION_FAILED'. Message: "Please check your DOTENV_KEY". Internally triggered by AES-GCM authentication tag verification failure ("Unsupported state or unable to authenticate data").Required handlingWrap decrypt() in try-catch. This is the most actionable error — it means the key and ciphertext do not correspond. Common during key rotation when old ciphertext is paired with a new key. Silent swallowing of this error leaves secrets unloaded.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3]
Sources
Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.
- [2]npmjs.com/package/dotenvDotenv
- [1]github.com/motdotla/dotenvmotdotla/dotenv
- [3]github.com/motdotla/dotenv/blobmotdotla/dotenv · main.js
- [4]github.com/motdotla/dotenvmotdotla/dotenv
- [5]github.com/motdotla/dotenvmotdotla/dotenv
Research notes
Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.
Sources: dotenv
Package: dotenv Version: 16.x (latest) Type: Configuration utility - .env file parsing and environment variable loading Weekly Downloads: 50M+ Last Updated: 2026-02-27
Official Documentation
Primary Documentation
- npm Package: https://www.npmjs.com/package/dotenv
- GitHub Repository: https://github.com/motdotla/dotenv
- GitHub Issues: https://github.com/motdotla/dotenv/issues
Package Characteristics
dotenv is a zero-dependency module that loads environment variables from a .env file into process.env. It follows the Twelve-Factor App methodology for storing configuration in the environment separate from code.
Core Purpose:
- Parse
.envfiles into key-value pairs - Load environment variables into
process.env - Support secure configuration management
- Enable environment-specific settings
API Reference
1. config() Method
Signature:
function config(options?: DotenvConfigOptions): DotenvConfigOutput
interface DotenvConfigOptions {
path?: string; // Path to .env file (default: ".env")
encoding?: string; // File encoding (default: "utf8")
debug?: boolean; // Enable debug output
override?: boolean; // Override existing process.env values
processEnv?: object; // Target object (default: process.env)
}
interface DotenvConfigOutput {
parsed?: DotenvParseOutput; // Parsed key-value pairs
error?: Error; // Error if loading failed
}
Purpose: Reads .env file, parses contents, and assigns values to process.env.
Return Value:
- On success:
{ parsed: { KEY: 'value', ... } } - On failure:
{ error: Error }
Source: https://github.com/motdotla/dotenv#config
Usage Example:
// Basic usage
require('dotenv').config();
// With options
const result = require('dotenv').config({
path: '/custom/path/to/.env',
encoding: 'utf8',
debug: true,
override: true
});
// Error handling
if (result.error) {
throw result.error;
}
Behavioral Claims:
POSTCONDITION 1: File Not Found Errors
- Claim: If the
.envfile is not found,config()returns an object with anerrorproperty containing the file system error. - Severity: ERROR
- Source: https://github.com/motdotla/dotenv - README "File not found: Check that
.envexists in the correct directory" - Evidence: Return value structure:
{ error: Error }when file doesn't exist - Common Bug: Developers call
config()without checking theerrorproperty, causing app to run with missing environment variables
POSTCONDITION 2: Parse Errors
- Claim: If the
.envfile contains invalid syntax,config()returns an object with anerrorproperty containing the parse error. - Severity: ERROR
- Source: https://github.com/motdotla/dotenv - README "Parse errors: Enable
debug: truefor console output" - Evidence: Parse engine throws errors for invalid syntax
- Common Bug: Invalid
.envsyntax silently fails, causing undefined variables
POSTCONDITION 3: Missing Required Variables
- Claim:
config()does not validate that required environment variables are present - developers must checkprocess.envmanually. - Severity: ERROR
- Source: Related package dotenv-safe exists specifically to validate required variables
- Evidence: https://www.npmjs.com/package/dotenv-safe - "MissingEnvVarsError will be thrown if any variables are missing"
- Common Bug: App uses
process.env.API_KEYwithout checking if it's defined, causing runtime errors or undefined behavior
POSTCONDITION 4: Encoding Errors
- Claim: If the
.envfile uses non-UTF-8 encoding and encoding option is not set, parse errors may occur. - Severity: WARNING
- Source: https://github.com/motdotla/dotenv - config options include
encodingparameter - Evidence: Default encoding is 'utf8', other encodings must be specified
- Common Bug: Files with special characters fail to parse correctly
2. parse() Method
Signature:
function parse(src: string | Buffer, options?: DotenvParseOptions): DotenvParseOutput
interface DotenvParseOutput {
[key: string]: string;
}
Purpose: Parses .env format string or Buffer into key-value object. Does NOT modify process.env.
Source: https://github.com/motdotla/dotenv#parse
Usage Example:
const dotenv = require('dotenv');
const buf = Buffer.from('BASIC=basic');
const config = dotenv.parse(buf);
// Returns: { BASIC: 'basic' }
Behavioral Claims:
POSTCONDITION 5: Parse Method Errors
- Claim:
parse()throws errors for invalid syntax (unlikeconfig()which returns errors). - Severity: ERROR
- Source: https://github.com/motdotla/dotenv - parse method throws exceptions
- Evidence: Function signature does not include error return value
- Common Bug: Developers call
parse()without try-catch, causing unhandled exceptions
3. populate() Method
Signature:
function populate(processEnv: object, parsed: DotenvParseOutput, options?: DotenvPopulateOptions): void
Purpose: Assigns parsed values to target object. Advanced usage for custom implementations.
Source: https://github.com/motdotla/dotenv#populate
Parsing Rules
Syntax Specification
Source: https://github.com/motdotla/dotenv#rules
The dotenv parser follows these rules:
-
Basic Assignment:
BASIC=basicResults in:
{ BASIC: 'basic' } -
Empty Lines:
- Empty lines are skipped
-
Comments:
# This is a comment KEY=value # Inline comment- Lines beginning with
#are comments #marks comment start unless value is quoted
- Lines beginning with
-
Empty Values:
EMPTY=Results in:
{ EMPTY: '' } -
Whitespace Trimming:
FOO= valueResults in:
{ FOO: 'value' }(trimmed) -
Quoted Values:
SINGLE='single quoted' DOUBLE="double quoted"- Inner quotes are preserved
- Whitespace inside quotes is preserved
-
JSON Values:
JSON={"foo": "bar"}Results in:
{ JSON: '{"foo": "bar"}' } -
Multiline Values:
MULTILINE="new\nline"- Double-quoted values expand
\nto newlines - Can use literal line breaks in quoted strings
- Double-quoted values expand
-
Backticks:
BACKTICK=`mixed "quotes"`- Supported for values with mixed quotes
Multiline Variables
Source: https://github.com/motdotla/dotenv#multiline-values
For multiline content like private keys:
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
Kh9NV...
-----END RSA PRIVATE KEY-----"
Or with escape sequences:
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END RSA PRIVATE KEY-----\n"
Error Handling Patterns
Standard Error Handling
Source: https://github.com/motdotla/dotenv/issues/705 - "dotenv import error handling seems not ideal"
Recommended Pattern:
const result = dotenv.config();
if (result.error) {
throw result.error;
}
console.log(result.parsed);
Common Mistakes:
-
No Error Checking:
// ❌ BAD - Silent failure dotenv.config(); const apiKey = process.env.API_KEY; // undefined if .env missing -
Missing Variable Validation:
// ❌ BAD - No validation dotenv.config(); const apiKey = process.env.API_KEY; // App crashes later when apiKey is undefined -
Correct Pattern:
// ✅ GOOD - Check for errors const result = dotenv.config(); if (result.error) { throw new Error(`Failed to load .env: ${result.error.message}`); } // ✅ GOOD - Validate required variables const apiKey = process.env.API_KEY; if (!apiKey) { throw new Error('API_KEY environment variable is required'); }
Environment Variable Injection Vulnerability
Source: https://github.com/google/zx/security/advisories/GHSA-qwp8-x4ff-5h87
Vulnerability: Environment Variable Injection in dotenv.stringify
An attacker with control over environment variable values can inject unintended environment variables into process.env, potentially leading to arbitrary command execution.
Mitigation:
- Avoid using quotes and backticks in environment variable values
- Enforce strict validation of environment variables before usage
- Use dotenvx for encrypted environment files
Security Best Practices
Source: https://github.com/motdotla/dotenv#security-issues
Critical Security Guidelines:
-
Never Commit
.envFiles:# ✅ Add to .gitignore echo ".env" >> .gitignore.envfiles should NEVER be committed to version control- Use
.env.exampleas template (without secrets)
-
Use Encrypted
.envFiles:- dotenvx (recommended successor) encrypts
.envfiles before committing - https://github.com/dotenvx/dotenvx - "a secure dotenv–from the creator of
dotenv"
- dotenvx (recommended successor) encrypts
-
Git Pre-Commit Hooks:
- Enable hooks to prevent accidental commits of secrets
- Use tools like git-secrets or similar
-
Secret Management in Production:
- Use dedicated secret management tools (AWS Secrets Manager, HashiCorp Vault, etc.)
- Avoid plaintext
.envfiles in production
-
Remove Accidentally Committed Secrets:
- If secrets are committed, remove from git history immediately
- Rotate all compromised credentials
-
Report Security Issues:
- Email: security@dotenv.org
- Do NOT report through public GitHub issues
Common Security Mistakes
Source: Various GitHub issues and security advisories
-
Credentials in Git:
# ❌ CRITICAL - Never do this git add .env git commit -m "Add config" git pushImpact: Credentials exposed in git history forever
-
Logging Parse Errors:
// ❌ BAD - May leak secrets in logs const result = dotenv.config(); if (result.error) { console.error('Failed to load .env:', result.error); }Impact: Sensitive values may appear in error messages
-
Missing .env in Production:
// ❌ BAD - App crashes dotenv.config(); // File not found in production const dbUrl = process.env.DATABASE_URL; // undefined db.connect(dbUrl); // CrashImpact: Application failure, potential exposure
Advanced Usage Patterns
ES6 Module Import
Source: https://github.com/motdotla/dotenv#usage
import 'dotenv/config'
Important: This must be the first import statement due to ES6 module execution order.
Common Mistake: Importing dotenv after other modules that access process.env
Node CLI Preload
node -r dotenv/config script.js
Loads dotenv before application code runs, avoiding the need to require it in code.
Custom Configuration via CLI
node -r dotenv/config script.js \
dotenv_config_path=/custom/.env \
dotenv_config_debug=true
Source: https://github.com/motdotla/dotenv/issues/705
Known Issue: When using dotenv.config() directly (not via import), the library doesn't read DOTENV_CONFIG_PATH environment variable, which can cause silent loading failures.
Related Packages
dotenv-safe
Source: https://www.npmjs.com/package/dotenv-safe
Extends dotenv to validate that required environment variables are defined.
Usage:
require('dotenv-safe').config({
allowEmptyValues: false,
example: './.env.example'
});
Throws: MissingEnvVarsError if variables in .env.example are missing from .env
Use Case: Enforcing required variables at startup
dotenvx
Source: https://github.com/dotenvx/dotenvx
Successor to dotenv with encryption support. Recommended for secure .env file management.
Features:
- Encrypt
.envfiles before committing - Decrypt at runtime
- Secure by default
dotenv-parse-variables
Source: https://www.npmjs.com/package/dotenv-parse-variables
Parses environment variables into appropriate types (numbers, booleans, arrays, etc.)
Twelve-Factor App Methodology
Source: https://github.com/motdotla/dotenv#should-i-commit-my-env-file
dotenv implements principles from The Twelve-Factor App:
"Store config in the environment separate from code"
Benefits:
- Environment-specific settings stay outside codebase
- Consistency across deployments
- No config changes in version control
- Easy environment switching (dev/staging/prod)
Common Error Scenarios
1. File Not Found
Scenario: .env file missing
Error:
{ error: Error: ENOENT: no such file or directory, open '.env' }
Detection:
const result = dotenv.config();
if (result.error && result.error.code === 'ENOENT') {
console.error('.env file not found');
}
2. Parse Error
Scenario: Invalid syntax in .env file
Example Invalid Syntax:
BROKEN KEY=value # Space in key name
Error:
{ error: SyntaxError: Unexpected token in .env file }
3. Missing Required Variable
Scenario: App expects variable that isn't defined
dotenv.config();
const apiKey = process.env.API_KEY; // undefined
apiService.connect(apiKey); // TypeError: Cannot read property of undefined
Solution:
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('API_KEY environment variable is required');
}
4. Called Too Late
Scenario: dotenv called after variables accessed
// ❌ BAD - dbUrl is undefined
const dbUrl = process.env.DATABASE_URL;
dotenv.config();
Solution:
// ✅ GOOD - config() called first
dotenv.config();
const dbUrl = process.env.DATABASE_URL;
5. Override Not Set
Scenario: Environment variable already exists, .env value ignored
# Shell
export API_URL=https://prod.example.com
# .env file
API_URL=https://dev.example.com
dotenv.config();
console.log(process.env.API_URL); // https://prod.example.com (not overridden)
Solution:
dotenv.config({ override: true });
console.log(process.env.API_URL); // https://dev.example.com (overridden)
Detection Patterns
Pattern 1: Unhandled config() Errors
Bad Pattern:
dotenv.config();
// No error checking
Detection Rule: dotenv.config() call without checking return value's error property
Pattern 2: Missing Variable Validation
Bad Pattern:
dotenv.config();
const apiKey = process.env.API_KEY;
// No validation that apiKey is defined
Detection Rule: process.env access without subsequent undefined check
Pattern 3: parse() Without Try-Catch
Bad Pattern:
const config = dotenv.parse(envString);
// parse() throws on error, no try-catch
Detection Rule: dotenv.parse() call not wrapped in try-catch block
TypeScript Support
Source: https://github.com/motdotla/dotenv - TypeScript definitions included
import * as dotenv from 'dotenv';
const result: dotenv.DotenvConfigOutput = dotenv.config();
if (result.error) {
throw result.error;
}
const parsed: dotenv.DotenvParseOutput | undefined = result.parsed;
Type Definitions:
DotenvConfigOptionsDotenvConfigOutputDotenvParseOptionsDotenvParseOutputDotenvPopulateOptions
Real-World Impact
Issue #705: Error Handling Concerns
Source: https://github.com/motdotla/dotenv/issues/705
Community feedback indicates the current error handling pattern is "not ideal" because:
- The
errorproperty is not prominently documented in types - Easy to miss checking for errors
- Silent failures are common
Recommendation: Use dotenv-safe for stricter validation
Issue #291: Variables Not Loading
Source: https://github.com/motdotla/dotenv/issues/291
Common issue: "dotenv won't load parsed env variables into process.env"
Causes:
- File path incorrect
- Called after variables accessed
- Override not set when variables already exist
- File encoding issues
Summary of Nark profiles
High-Priority Postconditions
- File not found errors MUST be handled (ERROR severity)
- Parse errors MUST be handled (ERROR severity)
- Missing required variables MUST be validated (ERROR severity)
- parse() calls MUST be wrapped in try-catch (ERROR severity)
Medium-Priority Postconditions
- Encoding errors should be handled (WARNING severity)
- dotenv.config() should be called before accessing process.env (WARNING severity)
- Credentials should never be committed to git (SECURITY severity)
Security Postconditions
- .env files MUST be in .gitignore (SECURITY severity)
- Environment variable injection vulnerabilities MUST be mitigated (SECURITY severity)
- Production deployments should use secret management tools (INFO severity)
References
- Official Documentation: https://github.com/motdotla/dotenv
- npm Package: https://www.npmjs.com/package/dotenv
- Snyk Security: https://snyk.io/advisor/npm-package/dotenv
- GitHub Issues: https://github.com/motdotla/dotenv/issues
- dotenv-safe: https://www.npmjs.com/package/dotenv-safe
- dotenvx (secure successor): https://github.com/dotenvx/dotenvx
- Twelve-Factor App: https://12factor.net/config
- Environment Variable Injection: https://github.com/google/zx/security/advisories/GHSA-qwp8-x4ff-5h87
Total Lines: 586 Last Updated: 2026-02-27 Confidence: HIGH (official documentation, security advisories, community issues)