Catch Failed Loads in error.hbs
Error Substates
When model() rejects, Ember renders the nearest error template with the rejection as `@model` — a clean way to show "post not found" or "server error".
What you'll learn
- Add an app/templates/error.hbs template
- Display the error message and stack
- Add a retry link that re-runs the model hook
When loading fails — the API is down, the record is missing, the user lacks permission — model() rejects. Ember’s error substate renders the nearest error.hbs with the rejection as @model.
Global Error Template
{{! app/templates/error.hbs }}
<section class="error">
<h1>Something went wrong</h1>
<p>{{@model.message}}</p>
<button type="button" {{on "click" this.retry}}>Retry</button>
</section> @model is the rejection — typically an Error. Show @model.message, status codes, or a generic message.
Per-Route Error Template
For the posts route, place a fallback at app/templates/posts/error.hbs:
{{! app/templates/posts/error.hbs }}
<h1>Couldn't load posts</h1>
<p>{{@model.message}}</p>
<LinkTo @route="index">Back to home</LinkTo> More specific wins over global.
Programmatic Error Handling
Override error as a route action to log or redirect:
// app/routes/post.js
import Route from '@ember/routing/route';
import { service } from '@ember/service';
import { action } from '@ember/object';
export default class PostRoute extends Route {
@service router;
@action
error(reason, transition) {
if (reason?.status === 404) {
this.router.transitionTo('not-found');
return false; // skip rendering the error substate
}
return true; // bubble up and render error.hbs
}
} Return false to stop the bubble; return true (or nothing) to let the error substate render.