All playbooks

Playbook 01 / 17

Debugging Env Var Issues

A concise checklist for incidents where local works but CI, staging, or production changes behavior.

The pattern

An environment variable is missing, renamed, differently cased, or scoped to the wrong environment, so the code silently falls back to a default that is only correct on one machine. These bugs feel random because the code is identical everywhere - only the environment differs. The failure usually lives in the gap between where config is read and where it is validated.

( 01 )Symptoms

How this failure announces itself.

  • warningTests pass locally but fail in CI, staging, or production with no code change in between.
  • warningThe service starts cleanly but behaves as if a feature flag, secret, or endpoint was never configured.
  • warningA secret-dependent path (auth, billing, webhooks) returns the wrong status in exactly one environment.
  • warningLogs show a default value being used where you expected an injected one.
( 02 )First moves

The first ten minutes — establish facts before touching code.

  • 1Log the resolved config the service actually booted with in the failing environment - not what you think it received.
  • 2Diff that resolved config against a working environment; the divergent key is usually visible immediately.
  • 3Trace the divergent key backwards: who sets it, who forwards it, who reads it, and which fallback applies when it is absent.
  • 4Check for case, prefix, and naming drift between the setter and the reader (APP_API_URL vs API_URL).
  • 5Reproduce locally by unsetting the variable - if that does not reproduce the failure, the variable is not the cause.
( 03 )Where to look

The code and config that usually owns this bug.

  • searchThe runtime config loader - every place that reads process.env (or equivalent) and what it falls back to when the key is absent.
  • searchCI and deployment env definitions - compare the exact key names against what the code reads, character by character.
  • searchContainer and orchestrator env mapping - a variable set in CI does not automatically reach the container runtime.
  • searchCase-sensitive key or file references - LOG_LEVEL vs log_level, .env vs .env.local load order.
( 04 )Common fixes

Fix the cause, then make the regression impossible.

  • buildValidate required env at startup and crash loudly with the missing key's name instead of limping along on defaults.
  • buildUse one canonical key name per value, read in exactly one module, so renames happen in a single place.
  • buildMake fallbacks explicit and environment-aware - a default that is safe locally can be wrong in production.
  • buildAdd a regression test that runs the config loader with the variable unset and asserts the visible failure.
( 05 )Prove the fix

A fix you can't demonstrate is a guess. Close the loop.

  • verifiedBoot the service with the fix in the previously failing environment and confirm the resolved config matches expectations.
  • verifiedUnset the variable on purpose and confirm the service now fails fast with a clear message instead of misbehaving.
  • verifiedRe-run the originally failing path and watch it pass for the stated reason, not by accident.