emberjs/ember.js · error · TransitionError

TransitionError

Error message

TransitionError

What it means

TransitionState.handleError wraps an error thrown during a transition (in a route hook like beforeModel/model/afterModel) in a TransitionError carrying the failing RouteInfo, whether the transition was aborted, and the state. The message is always 'TransitionError'; the original cause is on the `.cause`/error property. It signals the transition failed mid-flight at the given resolve index.

Source

Thrown at packages/router_js/lib/transition-state.ts:26

interface IParams {
  [key: string]: unknown;
}

function handleError<R extends Route>(
  currentState: TransitionState<R>,
  transition: Transition<R>,
  error: Error
): never {
  // This is the only possible
  // reject value of TransitionState#resolve
  let routeInfos = currentState.routeInfos;
  let errorHandlerIndex =
    transition.resolveIndex >= routeInfos.length ? routeInfos.length - 1 : transition.resolveIndex;

  let wasAborted = transition.isAborted;

  throw new TransitionError(
    error,
    currentState.routeInfos[errorHandlerIndex]!.route!,
    wasAborted,
    currentState
  );
}

function resolveOneRouteInfo<R extends Route>(
  currentState: TransitionState<R>,
  transition: Transition<R>
): void | Promise<void> {
  if (transition.resolveIndex === currentState.routeInfos.length) {
    // This is is the only possible
    // fulfill value of TransitionState#resolve
    return;
  }

  let routeInfo = currentState.routeInfos[transition.resolveIndex]!;

View on GitHub (pinned to 26f97246a8)

Solutions

  1. Inspect error.cause / the wrapped error to find the real failure.
  2. Add error handling in route hooks (try/catch or .catch) or an application-level error route/action.
  3. Handle the rejection where transitionTo is called: router.transitionTo(...).catch(fn).
  4. Use error routes (this.route('error', { path: '*:' })) or route error actions to recover gracefully.

Example fix

// before
router.transitionTo('post', id); // unhandled rejection wraps the API failure
// after
router.transitionTo('post', id).catch((e) => {
  console.error('transition failed:', e.cause ?? e);
});
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate route-hook preconditions before transitioning
async function safeTransition(router, name, model) {
  if (!model) return router.transitionTo('index');
  return router.transitionTo(name, model);
}

Type guard

function isTransitionError(e) { return e instanceof Error && e.message === 'TransitionError'; }

Try / catch

router.transitionTo('post', id).catch(e => {
  if (isTransitionError(e)) {
    const cause = e.cause ?? e.error;
    console.error('transition hook failed:', cause);
    router.transitionTo('error');
  }
});

Prevention

When it happens

Trigger: Any route hook throws or rejects during transitionTo/handleURL; router handles it via handleError and rethrows as TransitionError.

Common situations: Model hooks rejecting on API failure; beforeModel redirects gone wrong; unhandled promise rejections in route lifecycle; assertion errors from guards.

Related errors


AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01). Data as JSON: /api/errors/cd73cc5588d79acf. Report an issue: GitHub.