Symptom
Reported during the 2026-05-01 fresh-VM tutorial run (chapter 6, "Test 6a manually"). The very first POST to /signup after wheels reload raised:
Lucee 7.0.0.395 Error (expression)
Can't cast Complex Object Type Struct to String
/Users/peter/ws/blog/app/models/User.cfc: line 13
13: this.email = Trim(LCase(this.email));
What's confusing about it
The error implicates LCase(this.email), suggesting this.email is a struct rather than a string. But:
- The submitted form body is plain key=value (
user[email]=alice@example.com&user[password]=hunter2).
- A debug print of
params after the failure confirmed params.user = {email: "alice@example.com", password: "hunter2"} — exactly the expected shape.
- After adding the debug print,
wheels reload-ing, then removing the print and reloading again, subsequent POSTs to /signup returned a clean 302 to /posts and the user row was created correctly.
- The reporter could not reproduce after the second reload, even after
wheels stop && wheels start.
Hypothesis (not verified)
Possible model-loader cache state on the very first reload after a brand-new model file is added — the User.cfc object initialization may see a stale property bag where this.email is whatever struct-shaped intermediate the property bag holds before the request-time bind happens. Once Lucee compiles + Wheels' model loader hands out the second-and-onward instance, the cache is correct and the issue self-heals.
If that's right, the underlying bug is in the model-loader's first-instance pathway after a ?reload=true that introduced a new model. It would hit any new model whose first instance is created inside an action, not just User.
What would help when reproducing
- Watch
application.wheels.models.User inspectability across the boundary
- Capture the value of
this.email via a dump(this.email) BEFORE the Trim(LCase(...)) call
- Check whether
onMissingMethod or a property-bag initializer is involved
Reproducer (reportedly intermittent)
wheels new blog then walk chapters 1-5 of the tutorial
- Add
app/models/User.cfc per chapter 6 step "Add a User model"
- Run the matching migration
wheels reload
- POST to
/signup immediately
If the bug fires, the fix is wheels reload once more (the second reload was sufficient on the original run).
Workaround for tutorial users
Reload twice before the first signup attempt, OR wheels stop && wheels start instead of reload after adding the User model. The chapter's checkpoint (Visit /signup, create an account...) doesn't currently mention either workaround.
Related context
Symptom
Reported during the 2026-05-01 fresh-VM tutorial run (chapter 6, "Test 6a manually"). The very first POST to
/signupafterwheels reloadraised:What's confusing about it
The error implicates
LCase(this.email), suggestingthis.emailis a struct rather than a string. But:user[email]=alice@example.com&user[password]=hunter2).paramsafter the failure confirmedparams.user = {email: "alice@example.com", password: "hunter2"}— exactly the expected shape.wheels reload-ing, then removing the print and reloading again, subsequent POSTs to/signupreturned a clean 302 to/postsand the user row was created correctly.wheels stop && wheels start.Hypothesis (not verified)
Possible model-loader cache state on the very first reload after a brand-new model file is added — the
User.cfcobject initialization may see a stale property bag wherethis.emailis whatever struct-shaped intermediate the property bag holds before the request-time bind happens. Once Lucee compiles + Wheels' model loader hands out the second-and-onward instance, the cache is correct and the issue self-heals.If that's right, the underlying bug is in the model-loader's first-instance pathway after a
?reload=truethat introduced a new model. It would hit any new model whose first instance is created inside an action, not justUser.What would help when reproducing
application.wheels.models.Userinspectability across the boundarythis.emailvia adump(this.email)BEFORE theTrim(LCase(...))callonMissingMethodor a property-bag initializer is involvedReproducer (reportedly intermittent)
wheels new blogthen walk chapters 1-5 of the tutorialapp/models/User.cfcper chapter 6 step "Add a User model"wheels reload/signupimmediatelyIf the bug fires, the fix is
wheels reloadonce more (the second reload was sufficient on the original run).Workaround for tutorial users
Reload twice before the first signup attempt, OR
wheels stop && wheels startinstead ofreloadafter adding the User model. The chapter's checkpoint (Visit /signup, create an account...) doesn't currently mention either workaround.Related context
4.0.0-SNAPSHOT+1667, brew-installed.