Skip to content

Add Error boundaries to template rendering - #1235

Open
megothss wants to merge 10 commits into
emberjs:mainfrom
megothss:error-boundary-rfc
Open

Add Error boundaries to template rendering#1235
megothss wants to merge 10 commits into
emberjs:mainfrom
megothss:error-boundary-rfc

Conversation

@megothss

@megothss megothss commented Sep 9, 2026

Copy link
Copy Markdown

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 Exploring label 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

  • The team believes the concepts described in the RFC should be pursued.
  • The label S-Proposed is removed from the PR and the label S-Exploring is added.
  • The Ember team is willing to work on the proposal to get it to Accepted

Checklist to move to Accepted

  • This PR has had the Final Comment Period label has been added to start the FCP
  • The RFC is announced in #news-and-announcements in the Ember Discord.
  • The RFC has complete prose, is well-specified and ready for implementation.
    • All sections of the RFC are filled out.
    • Any unanswered questions are outlined and expected to be answered before Ready for Release.
    • "How we teach this?" is sufficiently filled out.
  • The RFC has a champion within one of the relevant teams.
  • The RFC has consensus after the FCP period.

megothss added 10 commits March 6, 2026 18:58
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.
@megothss megothss mentioned this pull request Sep 9, 2026
11 tasks
@megothss megothss changed the title Error boundaries Add Error boundaries to template rendering Sep 9, 2026
ErrorBoundary uses Ember's named blocks syntax:

```gjs
import { ErrorBoundary } from '@ember/component';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@megothss megothss Sep 9, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you see my demo

I did not, that's super cool that you were able to do that!

image

🙈

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh actually, I think that needs rebased

can you rebase that, then I can see what you actually did

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

My bad. It looks better now.

As I explained in the RFC, I created this PR leaning heavily on AI to get into the ugly parts of the VM. It's just a proof of concept.

I'll be on vacation in the coming days but I'm happy to try making it work with the {{#try}}{{catch}}{{/try}} syntax once I'm back

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

  1. 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.

  2. 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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

template-lint is on the path to deprecation, actually #1214

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.

3 participants