DevTools Hub

Search tools

Search for a developer tool

Environment

.env Validator

Check a .env file for the dotenv parsing gotchas that silently corrupt values — # truncation, duplicate keys, unclosed quotes.

2 warnings
  • Value is truncated at an unquoted "#" — dotenv treats everything from "#" onward as a comment, so the actual value becomes "s3cr3t" instead of what looks intended. Wrap the value in quotes if "#" should be literal.
    Line 8
  • "DEBUG-MODE" isn't a valid identifier (letters, digits, underscore only, can't start with a digit) — this breaks "export"-based shell loading and, in JavaScript, "process.env.DEBUG-MODE" dot access (bracket access like process.env["DEBUG-MODE"] still works).
    Line 10
Parsed variables

Exactly what each key resolves to after quotes, escapes, and comment-truncation are applied — a quick way to spot a value that didn't come out the way you expected.

KeyValueLine
NODE_ENVproduction1
PORT30002
DATABASE_URLpostgres://user:pass@localhost:5432/mydb5
API_PASSWORDs3cr3t8
DEBUG-MODEtrue10

What this checks

Paste a .env file and it's parsed the same way the real dotenv npm package parses one — not a simplified approximation, the actual parsing rules, verified line by line against the real package. That matters because dotenv's behavior has a few sharp edges that don't show up until a value comes out wrong at runtime.

The headline one: an unquoted value is cut off at the first #, whether or not there's a space before it. API_PASSWORD=s3cr3t#backup doesn't set the password to s3cr3t#backup — it silently becomes s3cr3t, with #backup discarded as a comment. Wrapping the value in quotes (API_PASSWORD="s3cr3t#backup") is the fix, since quoted values keep # literally.

It also catches a duplicate key (dotenv keeps only the last one — the earlier value is silently gone), a key that isn't a valid identifier (breaks process.env.KEY dot access and shell export loading), an opening quote that's never closed anywhere later in the file (dotenv falls back to treating that line as unquoted rather than erroring), and a quoted value that spans several lines and swallows what look like other KEY=VALUE lines along the way — a real, surprising failure mode when a stray unmatched quote near the top of a file happens to find its match many lines later.

What it doesn't do

This intentionally doesn't support dotenv's obscure KEY: value colon-separator syntax (real, but rare enough that a line written this way is far more likely a typo for = than intentional) — those lines are flagged as missing an = here. It also doesn't expand $VAR references (core dotenv doesn't either — that's what the separate dotenv-expand package is for) or scan for hardcoded secrets; it's a parsing-correctness check, not a security scanner.

FAQ

Why does the # truncation happen even with a space before it?

It doesn't — dotenv's parser truncates at any # in an unquoted value regardless of what's next to it. This tool only warns about the cases where the # is directly attached to the preceding text (no space), since KEY=value # comment with a clear gap is almost always an intentional trailing comment working exactly as intended — flagging that too would just be noise.

Why is a hyphenated key only a warning, not an error?

dotenv itself accepts MY-KEY=value without complaint and sets it under that exact name — it's not invalid dotenv syntax. It only becomes a problem once something else tries to use it: a shell export, or JavaScript's process.env.MY-KEY, which doesn't even parse (it reads as subtraction). Bracket access, process.env["MY-KEY"], still works fine.

Related tools