diff --git a/modules/@angular/router/src/router.ts b/modules/@angular/router/src/router.ts index 139b72ea2d..5a65e4557f 100644 --- a/modules/@angular/router/src/router.ts +++ b/modules/@angular/router/src/router.ts @@ -526,6 +526,7 @@ export class Router { */ navigate(commands: any[], extras: NavigationExtras = {skipLocationChange: false}): Promise { + validateCommands(commands); if (typeof extras.queryParams === 'object' && extras.queryParams !== null) { extras.queryParams = this.removeEmptyProps(extras.queryParams); } @@ -1238,3 +1239,12 @@ function getOutlet(outletMap: RouterOutletMap, route: ActivatedRoute): RouterOut } return outlet; } + +function validateCommands(commands: string[]): void { + for (let i = 0; i < commands.length; i++) { + const cmd = commands[i]; + if (cmd == null) { + throw new Error(`The requested path contains ${cmd} segment at index ${i}`); + } + } +} diff --git a/modules/@angular/router/test/integration.spec.ts b/modules/@angular/router/test/integration.spec.ts index 5f7a3d2eae..cf781887f9 100644 --- a/modules/@angular/router/test/integration.spec.ts +++ b/modules/@angular/router/test/integration.spec.ts @@ -536,6 +536,17 @@ describe('Integration', () => { expect(cmp.recordedParams).toEqual([{name: '1'}]); }))); + it('should throw an error when one of the commands is null/undefined', + fakeAsync(inject([Router], (router: Router) => { + createRoot(router, RootCmp); + + router.resetConfig([{path: 'query', component: EmptyQueryParamsCmp}]); + + expect(() => router.navigate([ + undefined, 'query' + ])).toThrowError(`The requested path contains undefined segment at index 0`); + }))); + it('should push params only when they change', fakeAsync(inject([Router], (router: Router) => { const fixture = createRoot(router, RootCmp);