Severity: docs — affects every 3.x app that sources environment from .env. Real-world symptom: production VMs send environment=development to Sentry / debug bar / get(\"environment\").
Surfaced by: titan Phase 2.1 (Wheels 4.0 upgrade), 2026-05-15. Same root-cause as #2631 / #2637 (reloadPassword via .env).
Description
Titan's config/environment.cfm (and presumably the 4.0 starter-app template too) currently reads environment from .env like:
set(environment=application.env.environment);
The application.env.<key> chain isn't always populated before config/environment.cfm runs (depends on loadEnvFile() timing in public/Application.cfc). The result: even when .env has environment=production, the runtime sees environment=\"\" or stale value, and set(environment=...) resolves wrong.
In the titan case, this manifested as production VMs reporting environment=development in Sentry despite Ansible rendering .env with environment=production.
Fix shape (mirroring #2637)
Update upgrade guide section 4 and the 4.0 starter-app template's config/environment.cfm to use:
set(environment=env(\"environment\", \"production\"));
env() (introduced in 4.0 per #1985) handles the load-order issue and provides a safe default. Importantly: the default should be \"production\", not \"development\" — failing safe means a missing key resolves to prod, not dev.
Why this matters for v4.0.1
Every 3.x app that uses .env-driven environment (which is most) will silently emit wrong environment tags everywhere they're consumed. Sentry dashboards, error filters, debug-bar visibility, conditional behavior — all wrong.
Suggested
- Update
web/sites/guides/src/content/docs/v4-0-0/upgrading/3x-to-4x.mdx (or equivalent) under item 4
- Update
cli/lucli/templates/app/config/environment.cfm in the starter-app scaffold
- Optionally add this case to
wheels upgrade check's breaker scanner
cc @bpamiri
Severity: docs — affects every 3.x app that sources
environmentfrom.env. Real-world symptom: production VMs sendenvironment=developmentto Sentry / debug bar /get(\"environment\").Surfaced by: titan Phase 2.1 (Wheels 4.0 upgrade), 2026-05-15. Same root-cause as #2631 / #2637 (reloadPassword via
.env).Description
Titan's
config/environment.cfm(and presumably the 4.0 starter-app template too) currently readsenvironmentfrom.envlike:The
application.env.<key>chain isn't always populated beforeconfig/environment.cfmruns (depends onloadEnvFile()timing inpublic/Application.cfc). The result: even when.envhasenvironment=production, the runtime seesenvironment=\"\"or stale value, andset(environment=...)resolves wrong.In the titan case, this manifested as production VMs reporting
environment=developmentin Sentry despite Ansible rendering.envwithenvironment=production.Fix shape (mirroring #2637)
Update upgrade guide section 4 and the 4.0 starter-app template's
config/environment.cfmto use:env()(introduced in 4.0 per #1985) handles the load-order issue and provides a safe default. Importantly: the default should be\"production\", not\"development\"— failing safe means a missing key resolves to prod, not dev.Why this matters for v4.0.1
Every 3.x app that uses
.env-driven environment (which is most) will silently emit wrong environment tags everywhere they're consumed. Sentry dashboards, error filters, debug-bar visibility, conditional behavior — all wrong.Suggested
web/sites/guides/src/content/docs/v4-0-0/upgrading/3x-to-4x.mdx(or equivalent) under item 4cli/lucli/templates/app/config/environment.cfmin the starter-app scaffoldwheels upgrade check's breaker scannercc @bpamiri