JavaScript Basics: Validate Environment Variables in Node.js
Environment variables let you configure a program when you launch it. A setting that looks like a number or boolean still arrives as text, so checking it early prevents confusing failures later. This tutorial reads two settings, validates them, and prints the resulting configuration.
Prepare a scratch directory
You need Linux, Bash, the env, mktemp, rm, and rmdir utilities, a text editor, and Node.js on your PATH. These examples were tested with Node.js v24.19.0. They need no npm packages, package manifest, or network access. The program does not start a server or open a port.
Run these commands and keep this Bash session open:
node --version
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1The tested runtime prints:
v24.19.0Save the following files with your editor inside this directory. The example variables are DEMO_PORT and DEMO_VERBOSE. Each run sets or removes them for that child process only, preserving any existing settings in your Bash session.
Convert text into checked settings
Save as read-environment-config.mjs:
function readConfiguration(env) {
const portText = env.DEMO_PORT ?? "3000";
if (portText.length === 0 || /[^0-9]/u.test(portText)) {
throw new Error("DEMO_PORT must contain only decimal digits.");
}
const port = Number(portText);
if (!Number.isInteger(port) || port < 1 || port > 65535) {
throw new Error("DEMO_PORT must be between 1 and 65535.");
}
const verboseText = env.DEMO_VERBOSE ?? "false";
if (verboseText !== "true" && verboseText !== "false") {
throw new Error("DEMO_VERBOSE must be true or false.");
}
return Object.freeze({
port,
verbose: verboseText === "true",
});
}
try {
const config = readConfiguration(process.env);
console.log(`Port: ${config.port}`);
console.log(`Verbose: ${config.verbose}`);
} catch (error) {
console.error(`Configuration error: ${error.message}`);
process.exitCode = 2;
}The Node environment-variable guide explains why values arrive as strings. Missing settings produce undefined, so ?? supplies defaults. An explicitly empty value stays empty and fails validation instead of silently becoming a default.
The regular expression finds any character that is not an ASCII digit. Together with the empty-string check, it rejects whitespace, signs, fractions, and suffixes. Number then converts the whole string, and the range check accepts ports from 1 through 65535. This is the example’s configuration rule; no attempt is made to bind that port. Leading zeros are accepted and disappear when converted to a number.
For the boolean, compare exact strings. Boolean("false") is true because the string is nonempty, as MDN’s Boolean reference explains. Our rule accepts only lowercase true or false and converts them explicitly. The frozen result contains only a number and a boolean, keeping the rest of the program away from raw configuration text.
Run with defaults and overrides
Remove both example variables from this command’s environment:
env -u DEMO_PORT -u DEMO_VERBOSE node read-environment-config.mjsOutput:
Port: 3000
Verbose: falseNow provide both values for one run:
env DEMO_PORT=4200 DEMO_VERBOSE=true node read-environment-config.mjsOutput:
Port: 4200
Verbose: trueBoth successful runs exit with status 0. The env command avoids permanently exporting or unsetting anything in your current shell.
Load a small environment file
Node can load a file before your JavaScript starts. Save this nonsecret example as demo-config.env:
DEMO_PORT=5000
DEMO_VERBOSE=falseRun it with the file option before the script filename:
env -u DEMO_PORT -u DEMO_VERBOSE node --env-file=demo-config.env read-environment-config.mjsOutput:
Port: 5000
Verbose: falseA variable already present in the process environment takes precedence over the file. Verify that with a one-command override:
env -u DEMO_VERBOSE DEMO_PORT=6000 node --env-file=demo-config.env read-environment-config.mjsOutput:
Port: 6000
Verbose: falseThe file path is relative to the current directory. Node does not automatically load a file merely because it is named .env; this example explicitly selects it. See the Node v24.19.0 env-file option.
Use only an environment file you trust: it can also contain settings that affect Node itself. Keep credentials out of tutorial files, terminal commands, logs, and committed source. Never print the entire process.env object while debugging. This example prints only its two nonsecret settings.
Reject bad values before doing work
Check an out-of-range port. The if statement makes the expected failure safe to inspect even with Bash’s set -e enabled:
if env DEMO_PORT=0 DEMO_VERBOSE=false node read-environment-config.mjs; then
printf 'Unexpected success\n'
else
printf 'Exit status: %s\n' "$?"
fiOutput, including standard error:
Configuration error: DEMO_PORT must be between 1 and 65535.
Exit status: 2Check an ambiguous boolean spelling:
if env DEMO_PORT=3000 DEMO_VERBOSE=yes node read-environment-config.mjs; then
printf 'Unexpected success\n'
else
printf 'Exit status: %s\n' "$?"
fiOutput:
Configuration error: DEMO_VERBOSE must be true or false.
Exit status: 2An empty port or a value such as 3000abc fails the digits check. 65536 fails the range check. Both boundaries, 1 and 65535, are accepted. Validate once at startup, before connecting to services or writing application data, so a bad setting cannot leave work half done.
Clean up
Remove the two tutorial files and the empty directory:
rm -- read-environment-config.mjs demo-config.env
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirAcknowledgements
This post was created with assistance from AI.