Skip to content

feat(doctor): report a key an env file sets twice, and let the editor resolve it - #1403

Merged
geodro merged 2 commits into
mainfrom
feat/1390-duplicate-env-keys
Aug 8, 2026
Merged

feat(doctor): report a key an env file sets twice, and let the editor resolve it#1403
geodro merged 2 commits into
mainfrom
feat/1390-duplicate-env-keys

Conversation

@geodro

@geodro geodro commented Aug 8, 2026

Copy link
Copy Markdown
Member

A site showed postgres on every surface while the application ran on SQLite, and nothing anywhere said why. Its env file set DATABASE_URL twice: lerd read the first, the framework read the last, and both were behaving correctly.

Neither reading is wrong in general, which is why this reports rather than resolves. Symfony's dotenv parses into an array so a later assignment overwrites an earlier one and the last wins. Laravel loads through phpdotenv's immutable writer, which refuses to overwrite a name that is already set, so the first wins. lerd reads the first everywhere. A single rule cannot be right for both, and picking one silently is how a site ends up served from a database nobody chose.

The doctor names the key, how many times it is set, the value lerd uses and the value at the end of the file:

⚠ Env Keys
    DATABASE_URL is set 2 times (lerd reads "postgresql://...", the last is
    "sqlite:///%kernel.project_dir%/var/lerd_test.db") — in .env.local, and a
    framework reading the last value uses a different one than lerd does; keep
    the one you meant

Only dotenv files are ambiguous this way. A PHP file's duplicate has one answer the language decides, a second define being ignored and a later assignment replacing an earlier one, and lerd reads those the way PHP runs them.

The env editor shows the same conflict against the buffer rather than against disk, so it tracks edits, listing each occurrence with its line number and value. Keeping one drops the others, which leaves an ordinary unsaved change the user reviews and saves with the normal button, the way a staged missing key already works. Nothing is rewritten behind their back.

Driven against a real Symfony site carrying the duplicate, and against five other real sites to confirm none of them gains a finding.

Closes #1390

… resolve it

A site showed postgres on every surface while the application ran on SQLite, and nothing anywhere said why. Its env file set DATABASE_URL twice: lerd read the first, the framework read the last, and both were behaving correctly.

Neither reading is wrong in general, which is why this reports rather than resolves. Symfony's dotenv parses into an array so a later assignment overwrites an earlier one and the last wins; Laravel loads through phpdotenv's immutable writer, which refuses to overwrite a name already set, so the first wins. lerd reads the first everywhere. A single rule cannot be right for both, and picking one silently is how a site ends up served from a database nobody chose.

The doctor names the key, how many times it is set, the value lerd uses and the value at the end of the file, so the disagreement is visible instead of being something to work out from three surfaces contradicting each other. Only dotenv files are ambiguous this way: a PHP file's duplicate has one answer the language decides, and lerd reads those the way PHP runs them.

The env editor shows the same conflict against the buffer, with each occurrence and its line, and keeping one drops the others. That leaves an ordinary unsaved change the user reviews and saves with the normal button, the way a staged missing key already works, so nothing is rewritten behind their back.
@geodro
geodro requested a review from a team as a code owner August 8, 2026 08:12
The first cut stacked a banner per duplicated key in the editor, which reads well for the one key that prompted it and badly for a file with several: the keys need not be related, and a project can carry a handful for the same reason it carries one.

They collapse into a single banner now, saying how many keys are affected, and one modal lists them all: each key, each of its live occurrences with the line number and value, and a choice of which to keep. Nothing is preselected, because lerd cannot know which value the project meant and a default would read as a recommendation. Confirming drops the other occurrences from the editor buffer, bottom up so each removal leaves the earlier line numbers valid, and leaves an ordinary unsaved change to review and save with the normal button.

The doctor offers the same resolver rather than repeating the values it found: its finding carries a fix that sends the user to the env tab with the modal already asked for, and the tab opens it once the file has loaded. It is the one fix key that resolves nothing by itself, which is right for a conflict only the project can settle.
@geodro
geodro merged commit 3d70d37 into main Aug 8, 2026
3 checks passed
@geodro
geodro deleted the feat/1390-duplicate-env-keys branch August 8, 2026 08:28
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.

fix(env): a key set twice in one env file is read from the wrong end for some frameworks, and reported by none

1 participant