Authored by Jon Schlinkert, et al.
The .env file format aims to be a minimal, unambiguous configuration file format primarily used for setting environment variables in development environments. While the format has existed for many years with various implementations, this specification aims to standardize the expected behavior and provide clear guidance for parser implementations.
- Spec
- Comments
- Key/Value Pair
- Keys
- Values
- String
- Data Types
- Multi-line Values
- Error Handling
- Parser Reliability Requirements
- Variable Expansion
- Filename Extension
- MIME Type
- .env files MUST be valid UTF-8 encoded documents
- Files SHOULD be named
.env
(see Filename Extension for variations) - Whitespace means
tab
(0x09
) orspace
(0x20
) - Newline means
LF
(0x0A
) orCRLF
(0x0D
0x0A
) - Every non-empty line MUST be either:
- A comment
- A key/value pair
- A line continuation of a previous value (value only, keys MUST NOT span multiple lines)
- Empty lines are allowed and MUST be ignored
- Parsers MUST preserve empty values (e.g.,
FOO=
) - Parsers MUST preserve whitespace in values unless explicitly trimmed by quotes or other mechanisms
- Leading and trailing whitespace on a line MUST be ignored
Comments allow humans to add notes to .env files without affecting their parsing. The following comment styles are supported, listed in order of prevalence:
A hash symbol (#
) marks the rest of the line as a comment:
# This is a full-line comment
FOO=bar # This is an end-of-line comment
The following comment formats are also recognized by some parsers. Implementation of these formats is OPTIONAL:
; This is a semicolon comment
// This is a double-slash comment
Comments MUST NOT be recognized within values unless escaped:
SECRET="password#123" # The '#' is part of the value
MESSAGE="Hello # World" # The '#' after Hello is part of the value
The primary building block of an .env file is the key/value pair. Each pair MUST be on its own line unless using a line continuation character (see Multi-line Values). Keys MUST NOT span multiple lines.
KEY=value
Key/value pairs MUST be separated by an equals sign (=
). The first =
character on a line serves as the separator. Additional =
characters in the value are treated as part of the value:
URL=https://example.com/path?foo=bar&baz=qux # Valid, only first = is separator
Keys are case-sensitive and MUST:
- Begin with a letter (
A-Z
,a-z
) or underscore (_
) - Contain only letters, numbers, and underscores
- Not be empty
- Not span multiple lines
# Valid keys
FOO=value
foo=value
FOO_BAR=value
_FOO=value
# Invalid keys
123FOO=value # Cannot start with number
FOO-BAR=value # Cannot contain hyphens
.FOO=value # Cannot start with period
FOO\
BAR=value # Cannot span multiple lines
Traditional environment variable naming conventions RECOMMEND:
- Using uppercase letters
- Using underscores as separators
- Avoiding special characters
Values may contain any UTF-8 characters. Leading and trailing whitespace in values is significant unless the value is quoted:
FOO=bar # value is "bar"
FOO= bar # value is " bar"
FOO=bar baz # value is "bar baz"
FOO="bar" # value is "bar"
FOO=" bar " # value is " bar "
Empty values are valid and MUST be preserved:
EMPTY=
EMPTY="" # Same as above
Strings are the primary value type in .env files. They can be represented in two ways:
Unquoted values extend from the first non-whitespace character after the =
to the end of the line (or until a comment):
UNQUOTED=value with spaces
PATH=/usr/local/bin:/usr/bin:/bin
Values may be enclosed in single ('
) or double ("
) quotes. Quotes are required if the value:
- Contains leading or trailing whitespace you want to preserve
- Contains a comment character that should be treated as part of the value
- Contains line breaks (see Multi-line Values)
MESSAGE='Hello World'
PATH="C:\Program Files\App"
HASH="my#password" # Without quotes, #password would be a comment
While all values in .env files are technically strings, parsers MAY implement optional type coercion for common data types. If type coercion is implemented:
- It MUST be optional and easily disabled
- The default behavior SHOULD be string-only unless type coercion is an established standard in the ecosystem
- The implementation MUST document its coercion rules
- Coercion MUST NOT affect the original string value
When implemented, type coercion SHOULD follow these conventions:
The following string values MAY be interpretable as booleans:
DEBUG=true # true
DEBUG=false # false
DEBUG=True # true
DEBUG=False # false
DEBUG=TRUE # true
DEBUG=FALSE # false
String values that represent valid numbers MAY be coerced to numeric types:
PORT=8080 # Integer
TIMEOUT=12.5 # Float
SCIENTIFIC=1e-10 # Scientific notation
The following string values MAY be interpreted as null:
NULL=null
NULL=NULL
NULL=
Long values can span multiple lines using one of two methods. Note that while values can span multiple lines, keys MUST NOT:
Values (but not keys) enclosed in quotes can contain newlines:
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBAOsfi5AGYhdRs/x6q5H7kScxA0Kzrw
...
-----END RSA PRIVATE KEY-----"
INVALID_KEY="MULTI
LINE"=value # Invalid: keys cannot contain newlines
A backslash (\
) at the end of a line indicates the value continues on the next line. This can only be used for values, not keys:
LONG_MESSAGE=first line \
second line \
third line
INVALID_KEY=MULTI \
LINE=value # Invalid: keys cannot use line continuation
For line continuations:
- The backslash MUST be the last character on the line (excluding whitespace)
- Leading whitespace on continuation lines is included in the value
- Empty continuation lines are preserved
- Comments are not allowed on continuation lines
Invalid continuation examples that MUST trigger ENV005:
SECRET=password\ # comment
NEXT=value # Must trigger ENV005: comment after continuation
VALUE=first\ # Must trigger ENV005: dangling continuation at EOF
INVALID=test \ # Must trigger ENV005: whitespace before continuation
next line
Parsers MUST implement the following error handling:
- Description: A line that is not empty, not a comment, and does not contain a valid key/value pair
- Example:
foo\nbar\nbaz=qux
- Required behavior: Parser MUST throw an error and MUST NOT combine invalid lines
- Description: When the same key appears multiple times
- Required behavior: Parser MUST either: a) Use the last value (most common) b) Throw an error c) Use the first value
- Implementation MUST document which behavior it uses
- Description: Key contains invalid characters or starts with a number
- Required behavior: Parser MUST throw an error
- Description: A quoted value missing its closing quote
- Required behavior: Parser MUST throw an error
- Description: A backslash line continuation followed by a comment or EOF, or with preceding whitespace
- Required behavior: Parser MUST throw an error
SECRET=password\ # comment
NEXT=value # Should trigger ENV005
-
Description: Attempt to define a key across multiple lines (either through quotes or line continuation)
-
Required behavior: Parser MUST throw an error
-
Example:
MULTI\ LINE_KEY=value "MULTI LINE"=value
- Description: File contains non-UTF-8 characters
- Required behavior: Parser MUST throw an error
The .env format is used for configuration that directly affects application behavior and security. Therefore, parsers MUST prioritize reliability and predictability over convenience. This section outlines common pitfalls and required parser behavior.
Parsers MUST NOT silently ignore malformed input. The following examples show problematic input that MUST produce errors:
FOO # Invalid: no assignment
BAR=value # This line is valid, but parser must still error due to FOO
KEY VALUE # Invalid: missing assignment operator
PORT=8080 # This line is valid, but parser must still error due to previous line
USER=john\ # Invalid: dangling continuation
PASSWORD= # This line is valid, but parser must still error due to previous line
Each line MUST be validated independently before being combined with any other lines. Parsers MUST NOT:
- Combine non-empty lines that lack assignment operators
- Join lines unless explicitly continued with a backslash
- Skip validation of any non-empty, non-comment line
Examples of invalid line joining that MUST produce errors:
FOO
BAR=value # Some parsers incorrectly return { BAR: 'value' } or { 'FOO\nBAR': 'value' }
# Must error due to invalid FOO line
A=1\n
B # Some implementations might try to join B with previous line
FOO=value\n
BAR # Must not be joined with previous line
KEY=a
VALUE # Must error, not combine into KEY=aVALUE
Parsers MUST provide consistent error behavior:
- Same input MUST produce same errors
- Partial results MUST NOT be returned if any line is invalid
- Error messages SHOULD identify the specific line and issue
- Error codes MUST match those specified in Error Handling section
Example of incorrect partial results that MUST be avoided:
VALID_KEY=value
INVALID KEY=foo # Parser encounters invalid syntax here
ANOTHER_VALID=bar
# Parser must NOT return { VALID_KEY: 'value' } and then error
# Must error immediately without returning any values
To ensure reliable behavior, implementations MUST:
- Validate entire file before processing any assignments
- Throw appropriate error (see Error Handling) for first encountered issue
- Not attempt recovery from invalid syntax
- Not provide configuration options that bypass these requirements
The presence of valid lines in a file MUST NOT affect the parser's responsibility to error on invalid lines. This helps catch configuration issues early and prevents unpredictable behavior across different environments and implementations.
Variable expansion (e.g., FOO=${BAR}
) is explicitly NOT part of this specification. Implementations MAY provide variable expansion as an optional feature, but if they do:
- It MUST be disabled by default
- It MUST be explicitly documented
- It MUST define clear rules for:
- Syntax (e.g.,
${VAR}
vs$VAR
vs%VAR%
) - Scope (current file only, system environment, or both)
- Error handling for undefined variables
- Circular reference detection
- Maximum expansion depth
- Syntax (e.g.,
The canonical filename is .env
. Common variations include:
.env.local
.env.development
.env.test
.env.production
.env.example
When transferring .env files over the internet, the appropriate MIME type is application/env
. This designation is justified by the following characteristics that make .env files distinct from other formats:
-
Distinct Format
- Specific syntax rules for key-value pairs
- Defined comment styles
- Special handling of quotes and whitespace
- Line continuation mechanisms
- Rules for multi-line values
-
Specific Processing Model
- Strict parsing requirements
- Defined error conditions and handling
- Special security considerations for environment variables
- Load-time behavior distinct from other configuration formats
-
Unique Semantic Meaning
- Files represent environment variable declarations
- Values have specific runtime implications
- Format carries distinct security and operational considerations
While .env files may appear superficially similar to plain text or other configuration formats, their unique combination of syntax, processing requirements, and semantic meaning warrants a distinct MIME type. This is analogous to how application/json
exists despite JSON being representable as plain text, because the specific structure and processing model require unique identification.
The application/env
MIME type serves to:
- Properly identify .env files in transport
- Signal correct processing requirements to consuming systems
- Enable appropriate security handling
- Facilitate correct caching behavior
- Allow proper content negotiation
When transferring .env files over the internet, implementations MUST use the application/env
MIME type.