# Heroku CLI Bug `--env=` flag not behaving as expected. ## This minimal reproduction In this example repo, you'll see a "base" `.env` file which sets `BASE_ENV_VAR="value for base"` and has a blank `OTHER_ENV_VAR=`. The `.env.local` file declares `OTHER_ENV_VAR="value for other"`. The `.env.empty` is just an empty file, with no content. Finally the `Procfile` has a single entry that runs the `read_some_env_vars` Ruby executable script. That script just prints out the values of `ENV["BASE_ENV_VAR"]` and `ENV["OTHER_ENV_VAR"]`. Running the executable Ruby script directly results in exactly what we'd expect, both values being `not_set`: ```console $ ./read_some_env_vars ⚠️ BASE_ENV_VAR=not_set OTHER_ENV_VAR=not_set ⚠️ ``` Then using `heroku local:run` we would expect to see the values from the `.env`, and we do: ```console $ heroku local:run ./read_some_env_vars [OKAY] Loaded ENV .env File as KEY=VALUE Format ⚠️ BASE_ENV_VAR=value for base OTHER_ENV_VAR= ⚠️ ``` ## What's wrong? In the Heroku CLI prior to 8.2, passing `--env=/dev/null` (or any empty file) as the Environment file would result in nothing additional being loaded into the `ENV`. We would do this because we need to load multiple files, in a certain order, to match the behavior of `dotenv-rails`'s loading. Specifically, we want to load `.env.local` (ignored from our Git repo) first, and then `.env` (checked into Git). The `.env` hold base configuration needed, and a number of blank values with comments explaining what these are used for. Then the ignored-from-Git `.env.local` overrides some of the entries from the `.env` file. Using our earlier example, we'll now send `--env=/dev/null` and then `--env=.env.empty`. In both cases we'd expect to see output similar to directly running the `read_some_env_vars` script - `not_set` for both. But… instead we see the values from the `.env` file: ```console $ heroku local:run ./read_some_env_vars --env=/dev/null [OKAY] Loaded ENV /dev/null File as KEY=VALUE Format ⚠️ BASE_ENV_VAR=value for base OTHER_ENV_VAR= ⚠️ $ heroku local:run ./read_some_env_vars --env=.env.empty [OKAY] Loaded ENV .env.empty File as KEY=VALUE Format ⚠️ BASE_ENV_VAR=value for base OTHER_ENV_VAR= ⚠️ ``` If we use the `dotenv` executable to load `.env.local` before we run `heroku local`, we would only expect to see `BASE_ENV_VAR` as `not_set`, with `OTHER_ENV_VAR` having the value from `.env.local`. Again, we don't get what we'd expect. We do see the `OTHER_ENV_VAR` with the expected value from `.env.local`, so that's good! But we also see the `BASE_ENV_VAR` value from `.env`. And that's bad. ```console $ dotenv -f .env.local heroku local:run ./read_some_env_vars --env=/dev/null [OKAY] Loaded ENV /dev/null File as KEY=VALUE Format ⚠️ BASE_ENV_VAR=value for base OTHER_ENV_VAR=value for other ⚠️ ``` Finally, if we tell `heroku local` to explicitly load just the `.env.local`, we see it do that, and _also_ load the `.env`. Which it should not! ```console $ heroku local:run ./read_some_env_vars --env=.env.local [OKAY] Loaded ENV .env.local File as KEY=VALUE Format ⚠️ BASE_ENV_VAR=value for base OTHER_ENV_VAR=value for other ⚠️ ``` ## Conclusion Something changed from Heroku CLI 8.1.9 to 8.2+ wherein the `.env` file is being loaded regardless of the list of files given via the `--env` argument.