- Angular
NG04002 Cannot match any routesの直し方|原因一覧
NG04002: Cannot match any routes. URL Segment: '…' は、移動しようとした URL に合うルートが、ルート定義(Routes)のどこにも無いときのエラーです。 URL Segment: の後ろが、ルーターが合わせられなかった部分です。その文字列と、ルート定義の path を見比べると、原因がほぼ分かります。
ERROR RuntimeError: NG04002: Cannot match any routes. URL Segment: 'user'
at Recognizer.noMatchError (chunk-….js)
v22.2.2 で原因を1つずつ再現した結果です。
| 原因 | 開いた URL・操作 | 出たエラー(URL Segment) | 直し方 |
|---|---|---|---|
| パスの書き間違い | /user(定義は users) |
'user' |
path かリンクの文字を合わせる |
| 大文字・小文字の違い | /Users |
'Users' |
パスは大文字・小文字を区別する |
| routerLink の相対パス | /users で routerLink="detail/1" |
'users/detail/1' |
/ から書く、か相対の基準を直す |
| navigate の配列 | navigate(['detail', 1]) |
'detail/1' |
relativeTo を付ける、か / から書く |
| 遅延ロードの子の書き間違い | /admin/lists |
'admin/lists' |
子の Routes の path を合わせる |
pathMatch: 'full' に子がある |
/shop/item |
'shop/item' |
子を持つルートから pathMatch: 'full' を外す |
| 名前付き outlet のルートを直接開く | /menu(outlet: 'side') |
'menu' |
/home(side:menu) の形で開く |
| URL に丸かっこ | /users/(1) |
'users' |
( ) を %28 %29 にする |
ワイルドカード(**)が無い |
どれにも合わない URL | 上のどれか | 最後に { path: '**', … } を置く |
ワイルドカードの順番・path の先頭の /・pathMatch の付け忘れは、NG04002 とは別の形で出ました(後述)。本番サーバーでリロードすると 404 になるのは、ルーターが動く前の、サーバー側の別問題です(これも後述)。
確認環境:Angular 22.2.2(@angular/core・@angular/router・@angular/cli)、TypeScript 6.0.3、Node.js 24.21.0(Linux)。原因ごとにルート定義を用意して、開発ビルド(ng build --configuration development)と本番ビルド(ng build)を作り、Chromium(Playwright 1.56.1)で URL を開いてコンソールの出力と表示を記録しました。サーバー側の 404 は、index.html に戻さない静的サーバー(Python の http.server)と、戻すサーバーを curl で比べました。仕様の説明は angular.dev のドキュメントで確かめました(確認日 2026年10月13日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「NG04002 Cannot match any routesの直し方|原因一覧」
再現に使ったルート定義
以下の表の結果は、このルート定義で確かめました。
// app.routes.ts
import { Routes } from '@angular/router';
export const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: Home },
{ path: 'users', component: Users },
{ path: 'users/:id', component: UserDetail },
{ path: 'shop', component: Shop, pathMatch: 'full', children: [{ path: 'item', component: Item }] },
{ path: 'admin', loadChildren: () => import('./admin.routes').then(m => m.adminRoutes) },
{ path: 'menu', component: Menu, outlet: 'side' },
];
// admin.routes.ts(遅延ロードする子のルート)
export const adminRoutes: Routes = [
{ path: 'list', component: AdminList },
];
// app.ts
@Component({
selector: 'app-root',
imports: [RouterOutlet],
template: `<router-outlet /><aside><router-outlet name="side" /></aside>`,
})
export class App {}
provideRouter の基本は、関連記事「Angularルーティング設定|provideRouter・パラメータ・404」で扱っています。
エラー文:開発ビルドと本番ビルドの違い
同じ /user を開いたときの、コンソールの出力です。
開発ビルド(ng build --configuration development / ng serve)
ERROR RuntimeError: NG04002: Cannot match any routes. URL Segment: 'user'
at Recognizer.noMatchError (http://localhost:4472/chunk-34CJH2OV.js:35079:12)
本番ビルド(ng build)
ERROR y: NG04002: 'user'
at id.noMatchError (http://localhost:4473/chunk-PETYUQOW.js:4:181006)
本番ビルドでは「Cannot match any routes. URL Segment:」の文が消え、NG04002: 'user' だけになりました。 クラス名も短い名前(y・id)に変わります。本番のログ監視で NG04002 を探すときは、番号で探します。
どちらも、最初の表示(アドレスバーに直接入れた URL)で起きたときは、画面に何も出ず、アドレスバーは / になりました。画面内のリンクから移動したときは、前の画面のまま URL も変わりませんでした。
原因別の直し方
1. パスの書き間違い・大文字小文字
/user → NG04002: Cannot match any routes. URL Segment: 'user'
/Users → NG04002: Cannot match any routes. URL Segment: 'Users'
/users/ → エラーなし(/users に合った)
ルートの path は大文字・小文字を区別しました。末尾の / は、エラーにならず /users として表示されました。打ち間違いを防ぐには、パスを定数にしておき、ルート定義とリンクの両方で使う方法があります。
export const PATHS = { users: 'users', home: 'home' } as const;
{ path: PATHS.users, component: Users }
<a [routerLink]="['/', PATHS.users]">ユーザー</a>
2. routerLink の相対パス
/users の画面に、次のリンクを置いて押しました。
<a routerLink="detail/1">相対(detail/1)</a> <!-- → /users/detail/1:NG04002 -->
<a routerLink="1">相対(1)</a> <!-- → /users/1:表示された -->
<a routerLink="/users/1">絶対(/users/1)</a> <!-- → /users/1:表示された -->
ERROR RuntimeError: NG04002: Cannot match any routes. URL Segment: 'users/detail/1'
routerLink は、/ で始めないと、今いるルートの下を探します。 angular.dev の RouterLink の説明では、次のように決まっています。
| 書き方 | どこから探すか |
|---|---|
/users/1(/ で始まる) |
アプリの一番上(ルート)から |
1・./1(/ で始まらない) |
今いるルートの子 |
../users/1 |
1つ上の階層から |
URL Segment に、意図しない親のパス(ここでは users/)が付いていたら、相対パスが原因です。
3. Router.navigate は既定で一番上から
this.router.navigate(['detail', 1]); // → /detail/1:NG04002
this.router.navigate(['1'], { relativeTo: this.route }); // → /users/1:表示された
ERROR RuntimeError: NG04002: Cannot match any routes. URL Segment: 'detail/1'
routerLink と逆で、navigate() は relativeTo を付けない限り、一番上から探しました。 テンプレートの routerLink="1" を、そのまま navigate(['1']) に書き換えると、行き先が変わります。
4. 遅延ロード(loadChildren)の子のルート
/admin/list → 表示された
/admin/lists → NG04002: Cannot match any routes. URL Segment: 'admin/lists'
/admin → エラーなし。画面には何も表示されない
遅延ロードの子の path が合わないときも、URL Segment には親を含めた 'admin/lists' が出ました。親の loadChildren の書き方ではなく、読み込まれる側の Routes を見ます。
/admin は、子に path: '' が無いのにエラーになりませんでした。何も表示されないので、気づきにくい形です。/admin で一覧を出すなら、子に { path: '', redirectTo: 'list', pathMatch: 'full' } か { path: '', component: … } を足します。遅延ロードの書き方は、関連記事「Angular遅延ロード|loadComponentとloadChildren」で扱っています。
5. pathMatch: 'full' と子のルート
{ path: 'shop', component: Shop, pathMatch: 'full', children: [{ path: 'item', component: Item }] },
/shop → 表示された
/shop/item → NG04002: Cannot match any routes. URL Segment: 'shop/item'
pathMatch: 'full' は「URL の残り全部が path と同じときだけ合う」という意味です。/shop/item は shop と全部は同じではないので、子を見る前に外れました。
pathMatch |
合う条件 | 主な使いどころ |
|---|---|---|
'prefix'(既定) |
URL の先頭が path と同じ |
子を持つルート |
'full' |
URL の残り全部が path と同じ |
path: '' のリダイレクト |
angular.dev のリダイレクトの説明では、path: '' のリダイレクトで pathMatch: 'full' を付けないと、すべての URL がリダイレクトされる、と注意されています。v22.2.2 の開発ビルドでは、付け忘れると起動時に次のエラーで止まりました(後述)。
6. 名前付き outlet
{ path: 'menu', component: Menu, outlet: 'side' },
/menu → NG04002: Cannot match any routes. URL Segment: 'menu'
/home(side:menu) → 表示された(home と menu の両方)
outlet: 'side' のルートは、<router-outlet name="side" /> 用で、通常の URL のパスからは選ばれません。URL では (side:menu) の形で書きます。リンクなら [routerLink]="[{ outlets: { side: ['menu'] } }]" です。
7. URL に丸かっこがある
Angular の URL の書き方では、( ) は名前付き outlet の区切りです。そのため、パスの中に丸かっこが入ると、思わぬ解釈になりました。
/users/(1) → NG04002: Cannot match any routes. URL Segment: 'users'
/users/%281%29 → 表示された(users/:id の id が "(1)")
/home(foo) → エラーなし。/home になった
ID や検索語に丸かっこが入りうるときは、リンクを作る側で encodeURIComponent() をかけるか、routerLink の配列(['/users', id])で渡します。Angular の GitHub の Issue #50787 でも、URL の丸かっこで NG04002 が出る報告があります。
NG04002 にならない設定ミス
path の先頭に / を書いた
{ path: '/about', component: About }
開発ビルド
ERROR RuntimeError: NG04014: Invalid configuration of route '/about': path cannot start with a slash
(アプリの起動そのものが失敗し、画面は空のまま)
本番ビルド
エラーなし。/home は表示された(/about のルートは使えない)
path: '' のリダイレクトに pathMatch が無い
{ path: '', redirectTo: 'home' }
開発ビルド
ERROR RuntimeError: NG04014: Invalid configuration of route '{path: "", redirectTo: "home"}': please provide 'pathMatch'. The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.
本番ビルド
エラーなし
ルート定義の形のチェック(NG04014)は、開発ビルドだけで動きました。 本番ビルドでは何も出ないので、ng serve で一度は起動して確かめます。
ワイルドカードを先頭に置いた
export const routes: Routes = [
{ path: '**', component: NotFound }, // ← 先頭
{ path: 'home', component: Home },
];
/home → 404 の画面が表示された(エラーは出ない)
ルーターは配列の上から順に探し、最初に合ったルートを使います。** はどの URL にも合うので、必ず配列の最後に置きます。loadChildren で読み込む子の Routes にも ** を書いた場合は、その子の中で最後に置きます。
404 ページの作り方
NG04002 を出さず、「ページが見つかりません」を表示するには、最後にワイルドカードのルートを置きます。
// not-found.ts
import { Component } from '@angular/core';
import { RouterLink } from '@angular/router';
@Component({
selector: 'app-not-found',
imports: [RouterLink],
template: `
<h2>404 ページが見つかりません</h2>
<p><a routerLink="/">トップへ戻る</a></p>`,
})
export class NotFound {}
// app.routes.ts
export const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: Home },
{ path: 'users', component: Users },
{ path: 'users/:id', component: UserDetail },
{ path: '**', component: NotFound, title: 'ページが見つかりません' }, // ← 最後
];
/user → 表示: 404 ページが見つかりません(URL は /user のまま。エラーなし)
/home → 表示: home
| やり方 | URL | 向いている場面 |
|---|---|---|
{ path: '**', component: NotFound } |
打った URL のまま | 打ち間違いが分かるようにしたい |
{ path: '**', redirectTo: '' } |
トップに変わる | 404 画面を作らない小さなアプリ |
{ path: '**', redirectTo: '/404' } + /404 のルート |
/404 に変わる |
アクセス解析で 404 を数えたい |
ワイルドカードを置くと、NG04002 はもう出ません。開発中に原因を探すときは、次の withDebugTracing を使うか、一時的にワイルドカードを外すと、どの URL で外れたかが分かります。ID が存在しないとき(/users/999)の 404 は、ルートには合っているので、ワイルドカードでは出ません。リゾルバーやガードで判定して 404 の画面に移します(関連記事「Angularガードの使い方|CanActivateFnでログインリダイレクト」で扱っています)。
withDebugTracing で確かめる
withDebugTracing() を provideRouter に足すと、ルーターの内部のイベントがすべてコンソールに出ます。angular.dev では「ルーターのイベントの順番を調べるデバッグ用」と説明されています。
// app.config.ts
import { provideRouter, withDebugTracing } from '@angular/router';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes, withDebugTracing()), // 調べ終わったら外す
],
};
/user を開いたときの出力です(開発ビルド)。
Router Event: NavigationStart
NavigationStart(id: 1, url: '/user')
Router Event: NavigationError
NavigationError(id: 1, url: '/user', error: Error: NG04002: Cannot match any routes. URL Segment: 'user')
ERROR RuntimeError: NG04002: Cannot match any routes. URL Segment: 'user'
NavigationStart の url が、ルーターが実際に受け取った URL です。 routerLink の相対パスが原因のときは、ここに意図しないパス(/users/detail/1 など)が出ます。合ったときは、RoutesRecognized に、どのルートに合ったかの木構造が出ます。/home を開いたときは次の行が出ました。
Router Event: RoutesRecognized
RoutesRecognized(id: 1, url: '/home', urlAfterRedirects: '/home', state: Route(url:'', path:'') { Route(url:'home', path:'home') } )
本番ビルドでは、withDebugTracing() を付けても Router Event: の出力はありませんでした。開発ビルドで確かめます。
リロードすると 404 になる:サーバーの設定
ng serve では動くのに、本番サーバーに置いて /users でリロードすると 404 になる場合、これは NG04002 ではありません。ブラウザーがサーバーに /users というファイルを取りに行き、サーバーが「無い」と返している状態です。Angular はまだ読み込まれていません。
index.html に戻さない静的サーバーと、戻すサーバーで比べた結果です。
python3 -m http.server /users -> 404 / -> 200
index.html に戻すサーバー /users -> 200
| 見分け方 | NG04002 | サーバーの 404 |
|---|---|---|
| 画面 | Angular のアプリ(ヘッダーなど)は出る | サーバーのエラーページ |
| コンソール | NG04002 が出る |
Angular のログは何も出ない |
| ネットワーク | index.html は 200 |
開いた URL が 404 |
| 直す場所 | ルート定義・リンク | サーバーの設定 |
angular.dev のデプロイの説明では、ルーターを使うアプリは、無いパスへのリクエストに index.html を返すようサーバーを設定する、と書かれています(SPA モード・fallback と呼ばれる設定)。代表的な書き方です。
# nginx
location / {
try_files $uri $uri/ /index.html;
}
# Apache(.htaccess)
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /index.html [L]
// Firebase Hosting(firebase.json)
{
"hosting": {
"public": "dist/app/browser",
"rewrites": [{ "source": "**", "destination": "/index.html" }]
}
}
サーバーの設定を変えられないときは、provideRouter(routes, withHashLocation()) で /#/users の形の URL にする方法もあります。# の後ろはサーバーに送られないので、リロードしても index.html が返ります。
原因を探す順番
| 順番 | 見るもの | 分かること |
|---|---|---|
| 1 | エラーの URL Segment |
合わなかった URL。親のパスが付いていたら相対パス |
| 2 | ルート定義の path |
書き間違い・大文字小文字・pathMatch: 'full' |
| 3 | 遅延ロードの子の Routes |
子の path・path: '' の有無 |
| 4 | withDebugTracing() の NavigationStart |
実際に移動しようとした URL |
| 5 | ネットワークタブ | サーバーの 404 か、Angular のエラーか |
よくある質問
Q. ログイン後のコールバック(/callback?code=…)で NG04002 が出ます。
A. コールバック用の URL に合うルートが無いと、このエラーになります。{ path: 'callback', component: Callback } のように、受け取る画面のルートを用意します。クエリパラメータ(? の後ろ)はルートの照合に使われないので、path には書きません。
Q. ワイルドカードを置いたのに、まだ NG04002 が出ます。
A. 名前付き outlet の側で合わないときは、ワイルドカードでは受け止められませんでした。最後に { path: '**', component: NotFound } を置いた状態で /home(side:xyz) を開くと、NG04002: Cannot match any routes. URL Segment: 'xyz' が出ました。** は通常の outlet(primary)のルートだからです。URL Segment に出た部分が、どの階層の Routes で探されたかを確かめます。
Q. テスト(Vitest など)で NG04002 が出ます。
A. テスト用の provideRouter([]) に、テストで移動するルートが入っていない場合に出ます。テストで使うルートを provideRouter に渡します。テストの書き方は関連記事「Angular テスト Vitest 入門|v22の書き方・移行・実行結果つき」で扱っています。
Q. 本番だけでエラーが出ます。
A. 本番ビルドでは、ルート定義のチェック(NG04014)が動かず、先頭の / や pathMatch の付け忘れが黙って通りました。開発ビルドで起動して、NG04014 が出ないかを確かめます。リロードで 404 のときは、上のサーバーの設定です。
まとめ
- NG04002 は「URL に合うルートが無い」。
URL Segmentの文字列とルート定義を見比べる - 本番ビルドでは
NG04002: 'user'だけになる。ログは番号で探す routerLinkは/で始めないと今いるルートの子を探す。navigate()は逆で、relativeToが無ければ一番上から- 子を持つルートに
pathMatch: 'full'を付けると、子に届かない ( )は outlet の区切り。パスに入れるなら%28%29に- 404 画面は
{ path: '**', component: NotFound }を最後に。先頭に置くと全部 404 になる /で始まるpath・pathMatchの付け忘れは、開発ビルドでだけ NG04014 で止まる- リロードで 404 はサーバー側。
index.htmlに戻す設定を入れる
参考・出典
確認日はいずれも 2026年10月13日です。
- Angular「Common routing tasks」(Displaying a 404 page):https://angular.dev/guide/routing/common-router-tasks
- Angular「Redirecting routes」:https://angular.dev/guide/routing/redirecting-routes
- Angular「RouterLink」:https://angular.dev/api/router/RouterLink
- Angular「withDebugTracing」:https://angular.dev/api/router/withDebugTracing
- Angular「Deployment」(Routed apps must fall back to index.html):https://angular.dev/tools/cli/deployment
- angular/angular Issue #50787「Parentheses in url cause Error: NG04002」:https://github.com/angular/angular/issues/50787
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「NG04002 Cannot match any routesの直し方|原因一覧」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。