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
- Remove the inaccessibleByURL flag if the route should be deep-linkable, and make its model hooks self-sufficient.
- Redirect from an accessible parent/entry route instead of expecting direct URL entry.
- Catch the error at the router level and transition to a sensible default route.
- 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
- Only mark routes inaccessibleByURL when entry context truly cannot be reconstructed.
- Provide an alternative entry route for protected child routes.
- Document inaccessibleByURL routes so team members know deep links fail.
- Reconstruct required state from params in model hooks to keep URLs shareable.
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
- ${this.url}
- You attempted to mount the engine '${name}', but it is not r
- Defining a route serializer on route '${name}' outside an En
- Programmatic transitions by URL cannot be used within an Eng
- Defining a custom serialize method on an Engine route is not
AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01).
Data as JSON: /api/errors/7c5b30183c994d19.
Report an issue: GitHub.