emberjs/ember.js · error · UnrecognizedURLError

${_url}

Error message

${_url}

What it means

checkHandlerAccessibility throws UnrecognizedURLError when a route handler matched by the URL sets `inaccessibleByURL = true`. The URL resolves to routes, but one of them forbids being entered directly via URL, so the transition is treated as an unrecognized URL.

Source

Thrown at packages/router_js/lib/transition-intent/url-transition-intent.ts:36

  applyToState(oldState: TransitionState<R>) {
    let newState = new TransitionState<R>();
    let results = this.router.recognizer.recognize(this.url),
      i,
      len;

    if (!results) {
      throw new UnrecognizedURLError(this.url);
    }

    let statesDiffer = false;
    let _url = this.url;

    // Checks if a handler is accessible by URL. If it is not, an error is thrown.
    // For the case where the handler is loaded asynchronously, the error will be
    // thrown once it is loaded.
    function checkHandlerAccessibility(handler: R) {
      if (handler && handler.inaccessibleByURL) {
        throw new UnrecognizedURLError(_url);
      }

      return handler;
    }

    for (i = 0, len = results.length; i < len; ++i) {
      let result = results[i]!;
      let name = result.handler as string;
      let paramNames: string[] = [];

      if (this.router.recognizer.hasRoute(name)) {
        paramNames = this.router.recognizer.handlersFor(name)[i].names;
      }

      let newRouteInfo = new UnresolvedRouteInfoByParam(
        this.router,
        name,
        paramNames,

View on GitHub (pinned to 26f97246a8)

Solutions

  1. Remove the inaccessibleByURL flag if the route should be deep-linkable, and make its model hooks self-sufficient.
  2. Redirect from an accessible parent/entry route instead of expecting direct URL entry.
  3. Catch the error at the router level and transition to a sensible default route.
  4. Restructure the route so required context can be reconstructed from URL params.

Example fix

// before
export default Route.extend({ inaccessibleByURL: true });
// after
export default Route.extend({
  model(params) { return this.store.findRecord('post', params.post_id); }
});
Defensive patterns

Strategy: try-catch

Validate before calling

// Before deep-linking, confirm no handler in the chain sets inaccessibleByURL
function deepLinkAllowed(handlerInfos) {
  return handlerInfos.every(h => !h.handler || h.handler.inaccessibleByURL !== true);
}

Type guard

function isURLAccessible(handler) { return !(handler && handler.inaccessibleByURL === true); }

Try / catch

router.handleURL(url).catch(e => {
  if (e.name === 'UnrecognizedURLError') { router.transitionTo('index'); }
  else throw e;
});

Prevention

When it happens

Trigger: Navigating directly to a URL whose handler object defines inaccessibleByURL = true (common on engine route handlers or routes only reachable via transitionTo with contexts).

Common situations: Routes that require a parent context/model and are meant to be entered only via transitionTo('route', model); route-less/engine mount points; deep-linking to a child route that depends on in-memory state.

Related errors


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