Skip to content

fix: restore dotenv-expand behavior for expandEnv - #246

Open
lprnmns wants to merge 1 commit into
fastify:mainfrom
lprnmns:fix/expand-env-references
Open

lprnmns wants to merge 1 commit into
fastify:mainfrom
lprnmns:fix/expand-env-references

Conversation

@lprnmns

@lprnmns lprnmns commented Oct 23, 2026 •

Copy link
Copy Markdown

#222 (released in v7.0.0) replaced dotenv with node:util parseEnv. As part of that, expandEnv stopped using dotenv-expand and switched to a single regex pass over the merged keys. Some .env files that expanded correctly in v6 no longer do. Comparing dotenv-expand@10.0.0 (the version v6 used, called as before with { ignoreProcessEnv: true, parsed: merge }) with the current code:

input v6 (dotenv-expand 10) current
A=$B, B=$C, C=val A=val A=$C
A=${MISSING:-fallback} A=fallback A=${MISSING:-fallback}
A=${B:-x}, B=set A=x A=set:-x}
PRICE=\$5 PRICE=$5 PRICE=\$5

The first row is the most common case: a value can only use another variable's expanded value if that variable comes earlier in the merged object. So it depends on key order (and, through the merge, on whether the value came from .env, process.env or data). The third row shows that a default operator now produces a broken value even when the variable is set. (dotenv-expand returned x there, which doesn't match the shell either: B=set bash -c 'echo "${B:-x}"' prints set.)

This replaces expandVariables() with a small resolver that has the same syntax as before: $VAR, ${VAR}, ${VAR:-default} (unset or empty), ${VAR-default} (unset) and \$ for a literal $.

  • References are resolved recursively against the expanded value of the referenced key, so key order no longer matters.
  • A default value can itself contain references.
  • Unknown variables and circular references are left as written, like today's "keeps placeholder" behavior.
  • The existing regex quirks ($VAR} and an unterminated ${VAR) behave as before.

Tests: two cases in test/expand.test.js, one for chained references out of order and one for defaults, escapes, a numeric value and a self-reference. Both fail without the change. npm test (100% coverage, tstyche) and npm run lint pass. I also updated the expandEnv comment in the README.

@gurgunday gurgunday left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants