Skip to content

Fix default templates crashing when card model is transiently undefined - #5608

Closed
christse wants to merge 1 commit into
mainfrom
fix-default-template-undefined-model
Closed

Fix default templates crashing when card model is transiently undefined#5608
christse wants to merge 1 commit into
mainfrom
fix-default-template-undefined-model

Conversation

@christse

Copy link
Copy Markdown
Contributor

Problem

Production host intermittently crashes while rendering a card:

TypeError: Cannot read properties of undefined (reading 'constructor')
    at get cardInfoFieldDisplayNames (https://cardstack.com/base/default-templates/isolated-and-edit:10:50)

The default isolated/edit template derives the card class from this.args.model.constructor inside tracked getters, and dereferences this.args.fields unguarded. The host can render a format component for a tick while the model instance is still resolving — on initial load, and on a store re-resolve when an incremental index invalidation lands under an open card — so the first tracked getter throws and takes down the render. Reproduced repeatedly on a realm with heavy linksTo graphs and frequent CLI pushes (live invalidations of open cards).

Fix

  • Take the class from @cardOrField instead of model.constructor. Every format component already receives the class as an arg, independent of the instance — head.gts and embedded.gts use it for exactly this reason. isolated-and-edit.gts and field-edit.gts were the two templates digging it out of the instance instead.
  • Guard the @fields dereferences (displayFields, isThemeCard) and render the CardInfo edit header and notes footer only when @fields.cardInfo exists — invoking <@fields.cardInfo.notes /> with undefined @fields throws "attempted to invoke undefined component".

Behavior is unchanged whenever model/fields are present; a render pass with no data now produces an empty shell for that frame instead of throwing. This matches the defensive convention card-info.gts already follows throughout.

Verification

  • ember-template-lint clean on both files
  • host lint:types error count identical before/after (7 pre-existing, unrelated .at() lib-target errors)
  • The pre-commit eslint parse errors on these files are pre-existing for all packages/base gts files (the eslint config doesn't parse <template> there; the package's own lint is ember-template-lint, which passes)
  • Existing tests asserting the notes footer (card-basics-test) are unaffected by construction — the guards only change behavior when fields are absent, which previously crashed

Tracked in CS-12330.

🤖 Generated with Claude Code

The default isolated/edit template derived the card class from
model.constructor inside tracked getters. The host can render a format
component for a tick while the model instance is still resolving
(initial load, or a store re-resolve after an incremental index
invalidation lands under an open card), which crashed the render with
"Cannot read properties of undefined (reading 'constructor')".

The class is already passed to every format component as @cardOrField —
head.gts and embedded.gts use it for exactly this reason — so take it
from there instead of digging it out of the instance. Same rework in
field-edit.gts, which had the identical pattern. Guard the remaining
@fields dereferences and render the CardInfo edit header and notes
footer only when @fields is populated, so a render pass with no data
produces an empty shell instead of throwing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@christse

Copy link
Copy Markdown
Contributor Author

[Claude Code 🤖] Closing: this fix was made while working on a userland realm project, and platform changes shouldn't ride along with that work. The affected realm is shielded by a realm-side guarded default template, so nothing depends on this landing. CS-12330 remains the tracking ticket for the underlying host issue (default templates crash when the card model is transiently undefined); the fix-default-template-undefined-model branch stays available if the platform team wants to pick the @cardOrField approach up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant