Skip to tool
ecech.
💻 Developer & Code

PASSWORD="s3cret" Is Not the Same Password in Every Parser

There is no .env specification. Most libraries strip the quotes; Docker Compose's env_file historically kept them — and nothing logs why authentication failed.

Variables

Parser-dependent

meaning varies

Duplicates

Unreadable lines

Output



Lines worth looking at

Advertisement

How the calculation works

One line, two values DB_PASSWORD="s3cret" dotenv, most libraries s3cret Compose env_file, historically "s3cret" Eight characters instead of six. Authentication fails and nothing says why. There is no .env specification, so every implementation made its own rules.

How to Use This Tool

Paste a .env file and pick an output format. The conversion is the easy part; the list of parser-dependent lines underneath is the reason to use this rather than a regular expression.

There is no .env specification

The format grew out of shell scripts and a Ruby library, and every reimplementation since has made its own decisions about the edge cases. Node's dotenv, python-dotenv, Docker Compose, Vite, Next.js and the shell all differ somewhere. That is fine until a value travels between two of them.

Quotes are the expensive one

Most dotenv libraries treat surrounding quotes as delimiters and strip them, so DB_PASSWORD="s3cret" gives you s3cret.

Docker Compose's env_file historically did not: it read the whole thing after the equals sign, quotes included, so the same line gave you "s3cret" — eight characters instead of six. The failure mode is a service that cannot authenticate, no error mentioning quotes, and a value that looks correct in every log because the quotes read as formatting.

The safe habit is to quote only when the value actually needs it — leading or trailing spaces, a #, or a newline — and to leave everything else bare.

The hash character

Most parsers start a comment at an unquoted # that follows whitespace, so PORT=3000 # the app port gives 3000. Some start one at any unquoted #, which quietly truncates:

  • BRAND_COLOUR=#ff6600 becomes an empty string.
  • PASSWORD=ab#cd becomes ab.

Generated passwords contain hashes often enough that this is a real source of intermittent authentication failures. Quote any value containing one, and accept the quoting risk above as the smaller of the two problems.

The same escape, three ways A="one\ntwo" two lines B='one\ntwo' literal backslash n C=one\ntwo depends on the library Double quotes expand escapes, single quotes are literal, unquoted is a coin toss.
If a value needs a newline, use double quotes and test it in the runtime that will read it.

The rest of the rules, as most parsers implement them

  • Only the first equals splits. URL=postgres://u:p@h/db?a=1 is one value. The connection strings that make people nervous are actually fine.
  • An empty value is an empty string, not unset. EMPTY= sets the variable; your if not set check will not fire.
  • Everything is a string. DEBUG=false is the five-character string "false", which is truthy in most languages. This is the single most common .env bug.
  • Trailing whitespace is stripped by some parsers and kept by others. Invisible, and it breaks equality comparisons.
  • Duplicate keys usually resolve to the last one, silently.
  • Variable names should match [A-Za-z_][A-Za-z0-9_]*. Hyphens and dots work in some loaders and not in a shell.
  • export prefixes are accepted by most parsers and required by none.

Type inference is a convenience, not a rule

The inference option here turns 3000 into a number and true into a boolean in the JSON and YAML output, because that is usually what you want when moving config into a structured format. Be aware it is a decision this tool is making, not something the .env file said. Environment variables are strings all the way down, and version numbers like 1.10 become 1.1 if something helpfully parses them as numbers.

Advertisement

Frequently Asked Questions

Do I need quotes in a .env file?
Only when the value contains leading or trailing spaces, a # character, or a newline. Otherwise leave them off: most libraries strip surrounding quotes, but Docker Compose's env_file historically kept them, so a quoted password can arrive with the quotes attached and fail authentication with nothing in the logs explaining why.
Why is my .env value being cut off at the hash?
Because the parser treats # as the start of a comment. Most only do that for an unquoted # preceded by whitespace, but some do it for any unquoted #, which truncates colour codes like #ff6600 to nothing and passwords like ab#cd to ab. Quote values containing a hash.
Are .env values strings or typed?
Always strings. DEBUG=false is the five-character string 'false', which is truthy in most languages — comfortably the most common .env bug. Convert explicitly in your code rather than relying on the loader.
Can a .env value contain an equals sign?
Yes. Only the first equals splits the line, so database URLs with query parameters work without quoting or escaping.
What happens with duplicate keys in a .env file?
Nearly every parser keeps the last one and says nothing. That makes an accidental duplicate — usually from merging two files — hard to spot, because the file plainly contains the value you expected somewhere in it.
Does \n work in a .env value?
In double quotes, yes: most parsers expand it to a real newline. In single quotes it stays a literal backslash and an n. Unquoted, it depends on the library. If a value needs a newline, use double quotes and test it in the runtime that will actually read it.

Related tools in Developer & Code

Browse all Developer & Code tools
The Mac mini the ecech. site is built on, beside a handwritten note reading ecech.com.

Made by one person

ecech. is not a content farm. Every tool here is written and checked by hand, one at a time, by someone who wanted the tool to exist and could not find a version that showed its working.

No accounts and no sign-in, and nothing you type reaches a server — every calculation on this page runs inside your browser. The ads are served by Google and do set their own cookies, which is set out in full on the privacy page. More about the site.