Skip to content
NewBun 1.4.5 is out. Release notes
AphrodyBun

Linter · Rules

bun/no-env-at-module-scope

Disallow reading environment variables as soon as the module is loaded

A variable that's read at the top level of a file is read once, when the file is first imported. A test that sets process.env.API_URL after the import has no effect, and neither does code that loads the environment later. The module's behavior then depends on import order. Read the variable in the function that needs it.

The rule knows process.env, Bun.env, import.meta.env, and env imported from node:process. Assigning to a variable or deleting one isn't reported.

Configure

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"bun/no-env-at-module-scope" = "error" # or "warn"

Every option, set to its default:

bunfig.toml
[lint.rules]
"bun/no-env-at-module-scope" = ["error", {
  allow = ["NODE_ENV"],
}]

Examples

Reported:

const apiUrl = process.env.API_URL;

export function fetchUser(id) {
  return fetch(`${apiUrl}/users/${id}`);
}
import { env } from "node:process";

const { API_URL, API_KEY } = Bun.env;
const settings = { ...import.meta.env };
const port = Number(env.PORT);

Not reported:

export function fetchUser(id) {
  return fetch(`${process.env.API_URL}/users/${id}`);
}
process.env.TZ = "UTC";

const isProduction = process.env.NODE_ENV === "production";

Options

OptionDefaultWhat it does
allow["NODE_ENV"]Names of variables that can be read at the top level. It replaces the default list.
const isCI = process.env.CI === "true";
const { NODE_ENV, CI } = process.env;
const isProduction = process.env.NODE_ENV === "production";

When not to use it

A file like env.ts or config.ts that reads and checks the environment once at startup is doing this on purpose. Turn the rule off for that file.