Summary
Since #3036 (a6df6be, merged 2026-06-11), every password-gated reload (?reload=true&password=...), every URL environment switch (?reload=<env>&password=...), and the #3038 explicit allowEnvironmentSwitchViaUrl=true path return HTTP 500 on Adobe ColdFusion. The exception fires before applicationStop(), so the application never restarts — wheels reload (CLI drives the same URL) and the canonical reload documented across the guides are completely non-functional on Adobe. Lucee 7 is unaffected.
Repro (Adobe 2023 docker harness, develop f668c50)
cp tools/docker/adobe2023/{server.json,CFConfig.json,box.json} . && cp tools/docker/adobe2023/settings.cfm config/settings.cfm
printf '<cfscript>\nset(reloadPassword="smokepw");\n</cfscript>\n' >> config/settings.cfm
docker run -d -t --memory=3g -p 61750:62023 -v "$PWD":/wheels-test-suite wheels-test-adobe2023:v1.0.1
curl -s -o /dev/null -w '%{http_code}\n' 'http://localhost:61750/?reload=true&password=smokepw' # -> 500
curl -s -o /dev/null -w '%{http_code}\n' 'http://localhost:61750/?reload=testing&password=smokepw' # -> 500
Error page: You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members. — /wheels-test-suite/public/application.cfc: line 499.
Stack: BUILDREDIRECTURL (application.cfc:499) <- HANDLERESTARTAPPREQUEST (application.cfc:426) <- Global.cfc $invoke:320 <- $simpleLock:41 <- onRequestStart (Application.cfc:285).
Bare ?reload=true without a password (no restart path) still returns 200; the app keeps serving but can never be reloaded.
Root cause
public/Application.cfc::$buildRedirectUrl() has always assigned a string local named url (local.url = cgi.path_info; ... lines ~471-477). #3036 added a new block after those assignments that reads the URL scope unscoped:
if (
StructKeyExists(url, "reload") // line 499
&& !IsBoolean(url.reload)
&& Len(url.reload)
&& StructKeyExists(url, "password")
...
On Adobe CF, unscoped name resolution finds local.url (the string) before the URL scope → ScopeCastException. On Lucee, url is a reserved scope name that always wins → works. Pre-#3036 the function contained no URL-scope reads (git show a6df6beae~1:public/Application.cfc — only local.url and cgi.query_string), which is why this never fired before. This is CLAUDE.md anti-pattern #11 (never use a reserved scope name — url — as a local var) verbatim; #3036 added 6 StructKeyExists(url, ...) reads to this file, and the other call sites (onRequestStart, $handleRestartAppRequest, onApplicationStart handoff) are safe only because those functions happen not to declare a local.url.
Blast radius (all Adobe CF engines; verified on 2023)
Verified working end-to-end on Lucee 7 in the same session (302 preserving reload/password, switch applied, no loop; default block in testing strips params correctly) — the fix must not regress that.
Fix sketch
Rename the local in $buildRedirectUrl (e.g. local.url → local.redirectUrl) so the unscoped url reads resolve to the URL scope on every engine — or copy the needed URL keys into locals at function entry. Audit the function for any other reserved-scope locals while there.
Acceptance criteria
Found by the guide-behavioral-audit verifying web/sites/guides/src/content/docs/v4-0-0/core-concepts/environments-and-configuration.mdx ('reads them ... on every wheels reload').
🤖 Generated with Claude Code
Independently reproduced during the guide audit by 4 of 6 guide verifiers (core-concepts/environments-and-configuration.mdx, core-concepts/request-lifecycle.mdx, deployment/production-config.mdx, digging-deeper/caching.mdx).
Summary
Since #3036 (a6df6be, merged 2026-06-11), every password-gated reload (
?reload=true&password=...), every URL environment switch (?reload=<env>&password=...), and the #3038 explicitallowEnvironmentSwitchViaUrl=truepath return HTTP 500 on Adobe ColdFusion. The exception fires beforeapplicationStop(), so the application never restarts —wheels reload(CLI drives the same URL) and the canonical reload documented across the guides are completely non-functional on Adobe. Lucee 7 is unaffected.Repro (Adobe 2023 docker harness, develop f668c50)
cp tools/docker/adobe2023/{server.json,CFConfig.json,box.json} . && cp tools/docker/adobe2023/settings.cfm config/settings.cfm printf '<cfscript>\nset(reloadPassword="smokepw");\n</cfscript>\n' >> config/settings.cfm docker run -d -t --memory=3g -p 61750:62023 -v "$PWD":/wheels-test-suite wheels-test-adobe2023:v1.0.1 curl -s -o /dev/null -w '%{http_code}\n' 'http://localhost:61750/?reload=true&password=smokepw' # -> 500 curl -s -o /dev/null -w '%{http_code}\n' 'http://localhost:61750/?reload=testing&password=smokepw' # -> 500Error page:
You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members.—/wheels-test-suite/public/application.cfc: line 499.Stack:
BUILDREDIRECTURL (application.cfc:499) <- HANDLERESTARTAPPREQUEST (application.cfc:426) <- Global.cfc $invoke:320 <- $simpleLock:41 <- onRequestStart (Application.cfc:285).Bare
?reload=truewithout a password (no restart path) still returns 200; the app keeps serving but can never be reloaded.Root cause
public/Application.cfc::$buildRedirectUrl()has always assigned a string local namedurl(local.url = cgi.path_info; ...lines ~471-477). #3036 added a new block after those assignments that reads the URL scope unscoped:if ( StructKeyExists(url, "reload") // line 499 && !IsBoolean(url.reload) && Len(url.reload) && StructKeyExists(url, "password") ...On Adobe CF, unscoped name resolution finds
local.url(the string) before the URL scope →ScopeCastException. On Lucee,urlis a reserved scope name that always wins → works. Pre-#3036 the function contained no URL-scope reads (git show a6df6beae~1:public/Application.cfc— onlylocal.urlandcgi.query_string), which is why this never fired before. This is CLAUDE.md anti-pattern #11 (never use a reserved scope name —url— as a local var) verbatim; #3036 added 6StructKeyExists(url, ...)reads to this file, and the other call sites (onRequestStart,$handleRestartAppRequest,onApplicationStarthandoff) are safe only because those functions happen not to declare alocal.url.Blast radius (all Adobe CF engines; verified on 2023)
?reload=true&password=X— the canonical documented reload → 500, no restart?reload=<environment>&password=X— the new fix: make URL environment switching work through the app reload restart redirect #3036 feature → 500 (switch unreachable)set(allowEnvironmentSwitchViaUrl=true)(fix(events): honor explicit set(allowEnvironmentSwitchViaUrl=true) in production-like envs #3038) — unreachable via URL on Adobewheels reloadCLI — drives the same URL → same failureVerified working end-to-end on Lucee 7 in the same session (302 preserving
reload/password, switch applied, no loop; default block in testing strips params correctly) — the fix must not regress that.Fix sketch
Rename the local in
$buildRedirectUrl(e.g.local.url→local.redirectUrl) so the unscopedurlreads resolve to the URL scope on every engine — or copy the needed URL keys into locals at function entry. Audit the function for any other reserved-scope locals while there.Acceptance criteria
?reload=true&password=<pw>returns 302 and the application actually restarts (a settings.cfm edit is picked up)?reload=testing&password=<pw>from development switches the environment (302 preserves reload+password;/wheels/infoflips 200→404)set(allowEnvironmentSwitchViaUrl=true)in testing permits?reload=development&password=<pw>; unset stays blocked (Location strips params)Found by the guide-behavioral-audit verifying web/sites/guides/src/content/docs/v4-0-0/core-concepts/environments-and-configuration.mdx ('reads them ... on every wheels reload').
🤖 Generated with Claude Code
Independently reproduced during the guide audit by 4 of 6 guide verifiers (core-concepts/environments-and-configuration.mdx, core-concepts/request-lifecycle.mdx, deployment/production-config.mdx, digging-deeper/caching.mdx).