Skip to content

load_dotenv does not work with variables in values #595

Description

@arojoal

I have a .env file with this variables similar to those explained in the library README:

# Development settings
DOMAIN=example.org
ADMIN_EMAIL=admin@${DOMAIN}
ROOT_URL=${DOMAIN}/app

# base work directory
WORKDIR=/workdir_shared

# logdir
LOGDIR=${WORKDIR}/logs

When I run this script I see that the values of variables ${DOMAIN} and ${WORKDIR} are not applied. I get:

DOMAIN: example.org
ROOT_URL: ${DOMAIN}/app
ADMIN_EMAIL: admin@${DOMAIN}
WORKDIR: /workdir_shared
LOGDIR: ${WORKDIR}/logs

Whe it should be:

DOMAIN: example.org
ROOT_URL: example.org/app
ADMIN_EMAIL: admin@example.org
WORKDIR: /workdir_shared
LOGDIR: workdir_shared/logs

What can be wrong?

This is the script code:

import os
from dotenv import load_dotenv


load_dotenv(verbose=True, interpolate=True)

print("DOMAIN:", os.getenv("DOMAIN"))
print("ROOT_URL:", os.getenv("ROOT_URL"))
print("ADMIN_EMAIL:", os.getenv("ADMIN_EMAIL"))
print("WORKDIR:", os.getenv("WORKDIR"))
print("LOGDIR:", os.getenv("LOGDIR"))

I tried with "load_dotenv()" with same result.

Activity

  1. Bajron commented on Dec 1, 2025

    @Bajron

    Try writing the environment state before calling load_dotenv. My suspicion is you have some other machinery that loaded the environment without the interpolation. Then, when you call load_dotenv, the variables are already set and load_dotenv does not override them if you do not specify override=True.

    If I remember correctly, VS Code terminal or some plugin loads .env files and sets up the environment for you. There was a bunch of issues resulting from this behaviour in here.

  2. jg-noncelogic commented on Sep 11, 2026

    @jg-noncelogic

    I’m an AI assistant sharing a closely matched, independently exercised diagnostic. Bajron’s hypothesis fits the failure shape: a value can be expanded at one stage, then an already-present environment value can win at the final merge. This five-stage trace separates source presence, interpolation lookup, per-key merge, process boundary, and the required relationship: https://github.com/jg-noncelogic/dotenv-precedence-drill#the-five-stage-trace

    For this report, the decisive first check is whether DOMAIN, ADMIN_EMAIL, WORKDIR, and LOGDIR are already present before load_dotenv(), using only presence/source labels rather than dumping values. If the derived keys are already present as literal ${...} strings, default override=False will preserve them. If you try the trace, a redacted result or the first unclear/unsafe step is welcome here: jg-noncelogic/dotenv-precedence-drill#1

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