Skip to content

Add strict parameter to load_dotenv() and dotenv_values() for fail-fast behavior #631

Description

@AhsanSheraz

Problem

python-dotenv currently fails silently in two critical scenarios:

1. Missing .env file — no error raised

load_dotenv("/wrong/path/.env")  # Returns False silently
# App continues with no config — production incident waiting to happen

While PR #388 improved this to return False (previously returned True), almost no one checks the return value. The common pattern is just load_dotenv() at the top of a module.

2. Invalid lines — silently logged as warnings

# .env file contains a typo (colon instead of equals):
# DATABASE_URL: postgres://localhost/db
load_dotenv()  # DATABASE_URL is silently missing
# App falls back to a default or crashes later with a confusing error

As described in PR #520: "I dealt with an .env file that accidentally contained an unparsable line. The software then set a default value and I almost wrote to a wrong database."

Community Demand

This is one of the most requested features, spanning multiple years:

The DEV Community article "Why load_dotenv() Is an Anti-Pattern" (2025) specifically calls out silent failures as the primary reason developers migrate away from python-dotenv to alternatives like pydantic-settings.

Proposal

Add a strict parameter (default False) to load_dotenv() and dotenv_values():

# Existing behavior preserved (strict=False by default)
load_dotenv()  # silent on missing file or parse errors

# Opt-in strict mode
load_dotenv(strict=True)  # raises on missing file or parse errors

Behavior with strict=True:

Scenario Current behavior With strict=True
.env file not found Returns False silently Raises FileNotFoundError
Invalid/unparseable line logger.warning() Raises ValueError with line number
Everything OK Returns True Returns True (unchanged)

Interaction with verbose

strict takes precedence over verbose. When both are True, the exception is raised without emitting a warning first — logging the same message before raising would be an anti-pattern (the exception already carries the information). When strict=False, verbose continues to work as before.

strict verbose Missing file behavior
False False Silent (returns False)
False True logger.info() warning
True False Raises FileNotFoundError
True True Raises FileNotFoundError (no warning logged)

Design Philosophy — Parser Correctness, Not Config Validation

This proposal intentionally stays within python-dotenv's existing philosophy of "populate what is available, let consuming code validate requirements." strict mode does not validate whether specific keys exist, whether values are the correct type, or whether the configuration is "complete" — that is the domain of tools like pydantic-settings.

What strict does is make python-dotenv honest about its own job: "did the file I was asked to read exist?" and "could I parse every line in it?" These are parser-level guarantees, not application-level config validation. The library should be able to tell you when it failed to do what you asked, rather than silently pretending everything is fine.

Backwards Compatibility

  • 100% backwards compatible — defaults to False, no behavior change for existing users
  • Opt-in only — users must explicitly pass strict=True

Scope

This addresses the umbrella of issues (#467, #297, #520, #591) with a single, clean API addition. The implementation touches main.py only (~20-30 lines), plus tests.

Related: #467, #297, #321, #520, #591, #164

Activity

  1. added 4 commits that reference this issue on Mar 15, 2026
    e23f928
    3fab2a8
    1ced9d9
    bdee098
  2. AhsanSheraz commented on Mar 15, 2026

    @AhsanSheraz
    Author

    Hey folks! 👋 This issue and the accompanying PR (#632) implement a strict mode that addresses the silent failure problems many of you have raised over the years. I'd love to hear your thoughts on the approach.

    Tagging people who've been involved in related issues/PRs:

    And others who commented on these issues:
    @iamsannyrai @ethsanders @larsks @cbarkinozer @kaskogsholm @reorx @guhcampos @kvfi @drkarthi @srgykuz @mbUSC

    TL;DR of the proposal:

    # Existing behavior unchanged (strict=False by default)
    load_dotenv()
    
    # Opt-in strict mode
    load_dotenv(strict=True)
    # → FileNotFoundError if .env missing
    # → ValueError if any line can't be parsed

    100% backwards compatible, opt-in only. The PR is up at #632 — would appreciate your feedback on whether this covers your use cases!

  3. bandtank commented on Mar 19, 2026

    @bandtank

    Thanks for the update. It looks like a decent solution. I do not recall the nuances of the problem because I moved away from dotenv a few years ago.

  4. larroy commented on Apr 7, 2026

    @larroy

    What about load_dotenv silently looking at parent directories for .env file and loading them? this is very problematic and insecure default behaviour which is not clearly documented and can lead to destroying production resources if inadvertedly loads wrong credentials from a parent directory such as user home.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions