Deleting a 'Useless' console.log Broke Production: Lazy Getters and Hidden Side Effects
Any build step that strips console calls, whether esbuild drop or Terser drop_console, can silently remove side effects hidden inside the logged expression and break production in ways that only surface after release. This incident is a concrete warning to audit logs for getters, Proxies, and custom conversion functions before automating their removal.
A routine cleanup removed 38 console.log calls across 47 changed files. Twenty minutes after release, the alert group went off: core product detail pages showed undefined prices for products with tiered pricing. The culprit was a single deleted line, console.log('price config:', product.priceConfig), which had been the only expression that triggered a lazy getter on a reactive product model.
That getter parsed and cached tiered pricing rules from raw data on first access; during rendering, code bypassed the getter and read the private field _priceConfig directly via bracket notation. With the log gone, the getter never fired, the private field stayed null, and the UI displayed undefined. Even esbuild's drop: ['console'] would have failed the same way, because the side effect lives in the argument expression, not the console call itself.
The post walks through three console.log side-effect patterns (Proxy dependency collection, toString/Symbol.toPrimitive, and WeakRef strong references), then recommends build-tool stripping with awareness of side effects, explicit init() methods over lazy implicit triggers, and ESLint rules that keep getters pure. The real lesson: in JavaScript, property access is a potential function invocation, so a log line can be load-bearing.
The failure wasn't caused by console.log itself but by code that depended on an implicit side effect during property access; the log just happened to be the first accessor.
The recommended fix, explicit init or eager initialization, removes the hidden dependency and makes the initialization contract visible, which is better engineering than preserving the log.
Build-time stripping tools are not side-effect-aware; teams that rely on them must treat the argument expressions of removed statements as potentially effectful.
The incident is read as a developer-discipline problem, not a logging problem: a single deleted console.log exposed a fragile lazy-getter design where the log was the only trigger. The consensus holds that such code should be left untouched if it runs, and the real culprit is the developer who created an implicit side-effect dependency. AI review is floated as a possible safety net, but the runtime nature of the failure makes static review insufficient.
So if it runs, don't touch it [black face]
Incisive!
Can AI review before committing solve this?
Not necessarily; these are runtime errors.
It's not about the log; it's about the colleague.