Add Error boundaries to template rendering - #1235
Conversation
Add RFC proposing a built-in <ErrorBoundary> component for catching synchronous render errors in the Glimmer VM.
- Remove Discourse mention, generalize to plugin architectures - Fix Solid.js and Preact documentation links - Add Svelte to framework parity list - Fix "only major framework" claim (Angular/Lit also lack it) - Remove vague route-level recovery subsection - Clean up unmaintained addon reference - Promote reference implementation into dedicated PoC section
Illustrate render failure blast radius with a concrete example
Add RFC emberjs#513 to prior discussion section, remove @onerror callback from unresolved questions
Drop two Motivation subsections that restated the opening paragraph. Answer the modifier question directly rather than calling the omission intentional. Modifiers run after the boundary's try has exited, and one may already have mutated the element, so recovery does not mean the same thing it does for render output. Say plainly that this is the most significant known gap. Add an Alternatives section on block syntax. The component form was chosen because it needs no tooling change, not because a keyword is the wrong answer. Rewrite Proof of concept: the prototype leaned heavily on AI assistance, is not a proposed implementation, and is not offered as a pull request against Ember. Ask reviewers to judge the API on its own merits. Retitle around the capability rather than the component, since the component is the proposed shape and not the substance of the proposal. Set start-date to the day the PR is opened, matching how the field is used in practice.
| ErrorBoundary uses Ember's named blocks syntax: | ||
|
|
||
| ```gjs | ||
| import { ErrorBoundary } from '@ember/component'; |
There was a problem hiding this comment.
First -- I think everyone wants the high level behavior, and you won't get any resistance there -- however:
I don't think this should or even could be a component
@wycats did some exploration on this way back when, and we were kinda looking at this syntax:
// ...
<template>
{{#try}}
whatever you want here
{{catch as |error|}}
do something with the error here
{{/try}}
</template>this necessarily cannot be a component, and must be deeply interwoven within the VM at the moment.
now, I think this will be way easier when we can get rid of the VM, and have rendering just be function calls.
The initial implementation of try/catch had a huge negative performance impact due to all the "userland" (from the browser's pespective) stack-management / unwinding.
There was a problem hiding this comment.
a high-level optimistic goal / thought:
- it would be great if we can change our compiled output in such a way that we can use the platform-native try/catch
There was a problem hiding this comment.
There was a problem hiding this comment.
Yeah, I agree that the choice for a component “ergonomics” here can be controversial. I only opted for it in this RFC because it would require absolutely no tooling changes because it won't add any new Handlebars syntax. There is prior art for it being a component in other frameworks.
And in this case it would be a special component class provided by Ember itself, just like it provides Component from @glimmer/component. The only difference in this case is that this component would provide the error boundary capabilities.
I'm not opposed to it being a Handlebars syntax in any way. I'm just explaining why I opted for the component in the first version of the proposal.
this necessarily cannot be a component, and must be deeply interwoven within the VM at the moment.
Yeah. Did you see my demo in https://megothss.github.io/ember-error-boundary-demo? It's possible to build it like a component, but it's indeed super interwoven into the GlimmerVM.
Anyway, I'm happy with whatever approach you choose if we manage to kick-start the process for this. I'm happy to help in whatever I can.
There was a problem hiding this comment.
oh actually, I think that needs rebased
can you rebase that, then I can see what you actually did
There was a problem hiding this comment.
a general point against the component tho -- is that this is a fundamental new behavior (and we've been working towards fundamental things being keywords anyway), yet does not introduce new syntax sigils, so tooling would not need to care about its existence (other than glint and eslint, which is easy to update) -- (see all the new keywords in 7.1 and 7.2)
There was a problem hiding this comment.
There was a problem hiding this comment.
As @NullVoxPopuli already mentioned - lots of interest. This feature has been high on my list of desired features as well. I'd put it in my top-3 desired changes (alongside scheduling and context APIs).
In terms of language-level vs component-level, I haven't personally given this enough thought - but my intuition has leaned component-level for some time. My intuition is guided by a belief that component syntax offers 2 distinct advantages (where a distinct advantage means a capability that we would not have if we introduced this at the syntax level instead)
-
error boundaries and features like suspense and async/await and generators are inherently intertwined. These thing are state machines, and states are represented very cleanly in component syntax by named blocks.
-
named blocks have no ordering requirement, and I think this is a good thing. There's lots of cases where putting error (or loading) variants of a state machine before the success variant are desirable. try/catch can only ever be ordered one way.
e.g. I'm not sure that the framework should enforce an opinion on:
<template>
<Boundary>
<:try></:try>
<:error></:error>
</Boundary>
</template>vs
<template>
<Boundary>
<:error></:error>
<:try></:try>
</Boundary>
</template>|
|
||
| ### Ecosystem implications | ||
|
|
||
| **ember-template-lint:** No new lint rules needed. ErrorBoundary uses standard named blocks syntax, which is already supported. |
There was a problem hiding this comment.
template-lint is on the path to deprecation, actually #1214


Propose adding Error Boundaries during Ember template rendering
Rendered
Summary
This pull request is proposing a new RFC.
To succeed, it will need to pass into the Exploring Stage, followed by the Accepted Stage.
A Proposed or Exploring RFC may also move to the Closed Stage if it is withdrawn by the author or if it is rejected by the Ember team. This requires an "FCP to Close" period.
An FCP is required before merging this PR to advance to Accepted.
Upon merging this PR, automation will open a draft PR for this RFC to move to the Ready for Released Stage.
Exploring Stage Description
This stage is entered when the Ember team believes the concept described in the RFC should be pursued, but the RFC may still need some more work, discussion, answers to open questions, and/or a champion before it can move to the next stage.
An RFC is moved into Exploring with consensus of the relevant teams. The relevant team expects to spend time helping to refine the proposal. The RFC remains a PR and will have an
Exploringlabel applied.An Exploring RFC that is successfully completed can move to Accepted with an FCP is required as in the existing process. It may also be moved to Closed with an FCP.
Accepted Stage Description
To move into the "accepted stage" the RFC must have complete prose and have successfully passed through an "FCP to Accept" period in which the community has weighed in and consensus has been achieved on the direction. The relevant teams believe that the proposal is well-specified and ready for implementation. The RFC has a champion within one of the relevant teams.
If there are unanswered questions, we have outlined them and expect that they will be answered before Ready for Release.
When the RFC is accepted, the PR will be merged, and automation will open a new PR to move the RFC to the Ready for Release stage. That PR should be used to track implementation progress and gain consensus to move to the next stage.
Checklist to move to Exploring
S-Proposedis removed from the PR and the labelS-Exploringis added.Checklist to move to Accepted
Final Comment Periodlabel has been added to start the FCP