| title | Router |
|---|---|
| description | The live route, every navigation as a story, the live route config, router setup and a route lint. |
The Routes tab reads the running app's Router. The top section, Live router, has five views. The bottom section, Source route config, lists the routes your files declare. When more than one page is connected, a Page picker chooses which one you see.
The route the page is on:
- The URL, and the browser URL when the two differ.
- The navigation in flight, with an Abort button.
- The document title, query params and fragment.
- Active routes: each active route with its component, params, data, and guards and resolvers. Tags mark lazy routes, inherited params, and whether a data value is static, resolved or inherited. The title row says when the title is inherited.
- Outlets: the outlet tree, with the inputs the router binds to each component and the
routerOutletDataeach outlet passes (what the routed component reads withinject(ROUTER_OUTLET_DATA)). The data shows as a redacted preview of at most 300 characters. Each activated outlet has a Show in Components button that opens the Components tab on the page the Routes tab shows, with the routed component selected and scrolled into view. If the component is no longer on that page, the Components tab says so. The button is hidden when the Components inspector is off or the page reports no element for the routed component.
Every navigation as one story:
- Where it came from, and who started it: a
RouterLink, the code that callednavigate, or back and forward. - The extras, redirect chains and loops.
- A phase bar: recognize, guards, resolve, activate.
- Guards and resolvers, lazy loads, reused components, HTTP requests, scroll, and the title afterwards.
- Router warnings, and the cancel or error reason. The tab explains NG04xxx errors.
- When the navigation error handler redirects, the navigation names the error handler as the cause and keeps the error that triggered it, with its error code.
Filter by URL, or check Only problems to keep the navigations that did not succeed and the ones in a loop. Only problems leaves out the navigations that Probe in app cancels, the way the problem count on the Navigations tab does. Each row has Replay and Copy repro (a markdown repro). Replay is off for a navigation whose URL is redacted or not relative, and a note under the row says why. Export JSON saves the list.
Clear empties the list and its loop warnings for the page you are looking at, so you can test a flow from a clean list without reloading the app. Other tabs keep their navigations. A navigation still running stays in the list. With actions.router set to false, Clear is off.
The Navigations view looks for loops in the recorded navigations. A loop is a chain that comes back to a URL it already visited:
| Loop | What the view detects |
|---|---|
| redirect loop | A chain of redirects returns to an earlier URL. The chain follows canMatch, guard, resolver and error handler redirects from one navigation to the next, plus the redirectTo inside each navigation. |
| navigation loop | Your code calls navigate or navigateByUrl within 500 ms of the previous navigation ending, and the chain returns to an earlier URL. |
redirect loop (NG04016) |
Angular stops a navigation with NG04016 because redirectTo entries of the config form a cycle. |
To see one, open the Routes lab of the demo app (/examples/routes). Guard loop makes two guards redirect to each other five times, then to Summary (a redirect loop). Navigation ping-pong navigates between Details and Summary from code (a navigation loop).
When the view finds a loop, a Loop detected section appears above the list. It shows the cycle of URLs, such as /account → /login → /account. Under it, each hop names its cause: the guard, the redirectTo entry or the navigate call. A last line lists the navigation ids, how many times the chain came back, how it ended and the guards involved.
Each navigation in a loop gets a loop badge and a red edge. Its details gain a Loop row with the cycle and the hop this navigation caused.
The live route config. The tab merges lazy children in once they load, and marks the active branch.
- Filter the routes by path, component or declaring file. While the filter is set, the summary shows the count, for example "2 of 14 routes", and a screen reader announces it as you type. If nothing matches, click Clear filters.
- Test a URL and click Predict to see which route matches it, or the nearest ones.
- Probe in app runs the real matcher without navigating.
- Fill in the params of a route and click Go to navigate to it. With a param left empty, Go marks the empty field and names the params to fill in.
- Read lazy reads the routes of a lazy route that has not loaded.
The result of Go and Read lazy shows under the row you clicked, and a screen reader announces it. Results and filled-in params belong to one page, so they are cleared when you pick another page.
How the router is set up (provideRouter, forRoot or other or unknown), the effective options with set or default badges, the enabled features, the strategies, the base href and hydration.
initialNavigation shows the mode that withEnabledBlockingInitialNavigation(), withDisabledInitialNavigation() or the forRoot option sets. The features map to these router features:
| Feature | Source |
|---|---|
componentInputBinding |
withComponentInputBinding() or bindToComponentInputs |
viewTransitions |
withViewTransitions() or enableViewTransitions |
navigationErrorHandler |
withNavigationErrorHandler() |
routerResources |
Router resources |
injectorCleanup |
withExperimentalAutoCleanupInjectors() |
preloading |
withPreloading() or preloadingStrategy, with the strategy name |
scroller |
withInMemoryScrolling() or the forRoot scrolling options |
debugTracing |
withDebugTracing() or enableTracing |
platformNavigation |
withExperimentalPlatformNavigation() (Angular 21.1 and later) |
Route config mistakes, each with a fix:
- Unreachable routes after
**, and duplicate paths. - A
:paramthat shadows a later literal path. This includes a:paramroute with children orloadChildren, because when the URL ends at it the router matches it with no child and never reaches the literal route. - Empty-path redirects with
pathMatch: 'prefix', which redirect every URL, and redirect cycles. - Redirect loops seen at runtime (rule
redirect-loop), with the hops and the guards involved. - Deprecated class guards and
canLoad. - Lazy chunks downloaded before a rejecting
canActivate. - Missing or duplicate titles, and param or input typos.
routerLinkActivewithoutariaCurrentWhenActive. The check covers everyRouterLinkon the page, also one bound as[routerLink]on an element that isn't an anchor.- Emails in URLs, and return URLs taken from query params.
Each finding says whether Angular throws, warns or does not warn. The lint skips lazy routes that have not loaded. It runs again after each navigation and config change, and keeps the current findings on screen while it does. Click Check again to rerun it.
If no check could run, the view says No checks ran and why: no page with a router is connected, or the page has not reported its route config yet. If the devtools server does not answer, the view shows an error with Retry.
The routes declared in your files: *.routes.ts and *routing.module.ts files, the files they lazy load, and Analog pages. Each row shows the path, the component or target, guards and resolvers, the title and the declaring file. Once the live config is available, the tab collapses this table. Show table opens it.
Components rendered by the router show their route and outlet in the Components tab.
The overlay finds the Router through Angular's debug API and reports the route, navigations, config and setup. The server reads your route files for the source table, and*.routes.server.ts for render modes.
The overlay reads the helper provideRouter() publishes (ng.ɵgetRouterInstance). For RouterModule.forRoot() apps, and on Angular 20.0 to 20.3.4 (which lack the helper), it looks for the Router token in the injectors instead. With several app roots, the router that has routes or has navigated wins. Before Angular 16.2 neither lookup exists; see On older Angular.
The live views need window.ng, so they need a development build. In a production build the overlay finds no Router, and Current says This page reports no Router.
When the debug API exists but lacks the provider helper (ng.ɵgetInjectorProviders), the tab runs in events-only mode. The route config is still read, so the tree and lint work. Setup detection is limited: the overlay can't find the preloader, the scroller or the router providers, so the Setup view says so and its features and options can show defaults.
The router reports one result for all the guards of a navigation. To see each guard's verdict and time, the devtools wrap every guard and resolver in the live config. Each row shows the guard, the route, its result (such as UrlTree /login) and its time.
Without that recording, the guards listed for a navigation are candidates: the canDeactivate guards of the page being left, and the canActivate and canActivateChild guards of the target.
false or a UrlTree.
Fix the code, then click Replay to run the same navigation again.
Click Copy repro to paste a markdown repro into an issue.
Type the URL into Test a URL.
Click Predict. A miss lists the nearest routes.
Click Probe in app to confirm with the real matcher. It runs canMatch and may load lazy chunks.
Read the findings, most severe first.
Each finding comes with a fix. Start with the ones where Angular stays silent.
Click Check again after the app reloads.
| Tool or resource | What it does |
|---|---|
pangular:explain-navigation |
Why a navigation failed or redirected, with any loop and the cause of each hop. Pass url or id to narrow it, limit for more than the last 5 (up to limits.navigations), perf for the slowest ones, or format: "repro" for a markdown repro of one navigation. |
pangular:inspect-route |
The route the page is on. Pass component (a component class, tag or link text) for the route a component was rendered for, or a link state. |
pangular:list-routes |
The live config with source files and example URLs. match predicts a URL, audit lists the guards of each page, resolveLazy loads the routes of a lazy route first. |
pangular:lint-routes |
The lint findings, including redirect loops seen at runtime. |
pangular:router-config |
The setup, including whether guard recording is on. |
pangular:scan-render-mode |
Which render mode a URL gets, from *.routes.server.ts. |
pangular:scan-routes |
Routes from your source files. |
pangular:navigate |
Acts on the router: go, abort and replay. |
pangular:probe-route |
Runs the matcher and canMatch guards for a URL without navigating. |
pangular:record-guards |
Turns per-guard and per-resolver recording on or off. |
pangular:router (resource) |
The active route tree and recent navigations of each page. |
navigate and probe-route only accept same-origin relative URLs that start with /. With actions.router set to false, the server drops navigate and probe-route, and keeps record-guards and list-routes with resolveLazy. See Tools.
Before Angular 16.2, Angular has neither ng.ɵgetRouterInstance nor ng.ɵgetInjectorProviders, so the overlay can't look the Router up by name. It reads the Router that a router link, the component an outlet renders or the root component holds, and asks the root injector for that class. If nothing on the page holds the Router, the tab shows no router data. See Supported Angular versions.
Record each guard and resolver in the Navigations view starts checked. Uncheck it to stop. Turning it off puts every original guard and resolver back. The page keeps the choice per browser tab, in sessionStorage, so it survives a reload. If the page does not answer, the checkbox returns to its previous state and the view shows the error. Agents use navigate with action: "instrument" and on.
Set up with tells provideRouter from forRoot by the ng.ɵgetRouterInstance helper. Angular 20.0 to 20.3.4 never publish it, so on those versions the overlay reads the root providers instead. The RouterModule.forRoot() guard token means forRoot or other, and the ROUTES token without that guard means provideRouter. If neither is there, the row shows unknown.
Aborting and probing use the currentNavigation signal and Navigation.abort(), which older versions lack. On those versions the action returns an error.
The tab lists only the last one, marked before Pangular Inspector connected, without timing or guard details. It also lists a navigation still running at that moment.
The devtools replace query, matrix and fragment values with secret-looking keys with [redacted]. They also redact tokens, Bearer values, and route params with secret-looking names such as :token. You can't replay a navigation with a redacted URL. See what the devtools redact.
The page keeps the last 50 navigations and 50 preloads. Set the navigation count with limits.navigations. Once older navigations are dropped, the Navigations view and explain-navigation say how many. The live config lists at most 200 routes per level (a route's children and its loaded lazy routes count as one level) and 1000 routes in total. The Config view and pangular:list-routes say how many routes were left out. The page reports at most 100 router links. After each DOM change, it checks at most 2000 elements that could hold a link. lint-routes and inspect-route say how many links past the first 100 were not checked. If the page has more elements than the check limit, the count is a minimum, and both tools also say how many elements were left out.
skipLocationChange and stops after recognition. canActivate, canDeactivate and resolvers do not run. If a canMatch guard or the navigation error handler redirects, the probe stops the redirected navigation too and names its target.
The probe runs your app's canMatch guards, so actions.router set to false turns it off, along with Go, Abort, Replay and Clear. Record each guard and resolver and Read lazy stay on.
The live config is available, so it is the better source. Click Show table to open the source list.
Routed components show their route and outlet.
File routes, server calls and render modes for Analog apps.
What is redacted, and how access is limited.
Every tool a coding agent can call.