Published: October 5, 2026 · by Srinu Desetti · motdotla/dotenv#1049 (opens in a new tab) · merged September 16, 2026
Fixing the typeof null Trap in dotenv's populate()
dotenv is how Node.js apps load .env files — roughly 50 million downloads a week. My contribution — merged by the creator of dotenv — fixes a bug where its public populate() function crashed with a raw TypeError when passed null, instead of throwing the clear OBJECT_REQUIRED error dotenv promises.

The Problem
populate() copies parsed key/value pairs into process.env. It has a safety check that should reject bad input with dotenv's own friendly error:
JavaScript has an old trap:
typeof null === 'object' // true — a quirk as old as the languageSo calling populate(process.env, null) walked right past the check, hit Object.keys(null) below, and crashed:
require('dotenv').populate(process.env, null)
// ❌ TypeError: Cannot convert undefined or null to object
// — a raw crash from deep inside, not dotenv's error
// expected:
// ✅ Error: OBJECT_REQUIRED: Please check the processEnv argument...And there was a second half: the first argument, processEnv, was never checked at all. So populate(null, parsed) also crashed with a raw TypeError — ironically, the error message text literally says "Please check the processEnv argument", but the code never checked it.
Why null sneaks in: config loaders, JSON parsers, and lookup helpers commonly return null when something is missing. Pipe that into populate() and — before this fix — you got a cryptic crash from inside dotenv's internals instead of an error that names the actual problem.
The Fix: One Line
Four conditions, covering both arguments:
processEnv === null— the explicit null checktypeofcan't do.typeof processEnv !== 'object'— rejects strings, numbers,undefined.parsed === null— same null check for the second argument.typeof parsed !== 'object'— the original check, kept as-is.
I deliberately kept the existing error message and error code unchanged — the message was already correct; now the code finally does what the message says. No existing behavior or test broke.
The Tests
Two regression tests in tests/test-populate.js lock the fix in:
Without these, one refactor could silently reintroduce the crash — the tests make sure nobody can quietly re-break it.
How I Found and Verified It
No issue was filed — I found the bug myself by auditing the code:
- Read
lib/main.jsend to end and spotted thetypeof nulltrap in the guard. - Proved it with Node — ran both calls; both crashed with raw TypeErrors.
- Checked GitHub first — no open or closed issue reported it, and no competing PR existed. The lane was completely free.
- Ran the full test suite before and after — the only failures were three pre-existing Windows path quirks that fail identically on clean master. All 4 CI checks passed on the PR.
A community reviewer verified the bug independently and approved; motdotla, the creator of dotenv, merged it four days after I opened it.
Impact
- A real crash in a public API of a package with ~50M weekly downloads and ~20.5k stars is gone.
- Developers get the error dotenv promises: when null sneaks in, the message says exactly what's wrong instead of a cryptic
TypeErrorthey have to debug. - Minimal, surgical diff: one changed line plus 20 lines of tests — no parsers touched, no messages changed, no behavior altered for valid input.
What I Contributed
- Audited
lib/main.jsand identified thetypeof nulltrap plus the completely uncheckedprocessEnvargument. - Implemented the four-condition guard covering both arguments while preserving the existing error message and code.
- Added two regression tests proving both null paths throw
OBJECT_REQUIREDinstead of crashing. - Verified the fix against the full test suite and shepherded the PR through review to merge.
View the pull request → motdotla/dotenv#1049 (opens in a new tab)
← Previous: Multer filename decoding · All contributions →
Frequently Asked Questions
Why does typeof null return 'object' in JavaScript?
It's a bug from the very first JavaScript implementation in 1995: values carried a type tag, and the tag for objects was 0 — the same representation null used. Fixing it would break the web, so it was standardized as-is. Any validation using only typeof x === 'object' silently accepts null.
What happened before this fix when you passed null to populate()?
The guard passed (because typeof null === 'object'), execution reached Object.keys(null), and Node threw a raw TypeError: Cannot convert undefined or null to object — a confusing crash from dotenv's internals instead of the documented OBJECT_REQUIRED error.
Why check the processEnv argument too?
It was never validated at all, so populate(null, parsed) crashed the same way. The irony: the error message text already said "Please check the processEnv argument" — the code just never did. The fix makes the code match its own message.
Did the fix change dotenv's error message or behavior for valid input?
No. The error message and error code are unchanged, no other function was touched, and every existing test still passes. The diff is one changed line plus two regression tests — valid input behaves exactly as before.