Skip to content

Intermittent 'Can't cast Complex Object Type Struct to String' on first POST /signup after cold reload #2412

@bpamiri

Description

@bpamiri

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)

  1. wheels new blog then walk chapters 1-5 of the tutorial
  2. Add app/models/User.cfc per chapter 6 step "Add a User model"
  3. Run the matching migration
  4. wheels reload
  5. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions