参考図書
Next.jsで動的ページを作成した際、getStaticPaths の書き方によっては次のようなエラーが発生しました。
Server Error
Error: The provided path blog/category/technology does not match the page: /blog/category/[slug].
この原因と解決策を整理しました。
1. エラーが発生した例
export const getStaticPaths = async () => {
return {
paths: ['blog/category/technology'], // ←文字列の配列
fallback: false,
};
};
文字列配列で書いた場合、Next.js は [slug] に何を渡せば良いか判断できず、エラーとなりました。
2. 文字列形式と相対パスの問題
基本的なこととして、文字列配列の場合、先頭に/がないと 相対パス として扱われます。
Next.js が「相対パス」として解釈する場合
paths に文字列で / がない場合、Next.js はその文字列を ページファイルの場所を基準にした相対パスとして扱おうとします。
例えばページファイルが /pages/blog/category/[slug].jsx にある場合:
paths: ['blog/category/technology']
Next.js は「[slug].jsx のフォルダを基準にして、blog/category/technology というサブパスがあるか?」と解釈しようとします。
結果、[slug] にマッピングできずに 「パスがページにマッチしない」 エラーが出ます。
言い換えると「[slug] に何を渡せばいいか Next.js が分からない」状態です。
/ を付けるとどうなるか
paths: ['/blog/category/technology']
- 先頭
/があると ルートからの絶対パス として扱われる -
/pages/blog/category/[slug].jsxの[slug]に'technology'を渡せる - 動的ページが正しく生成される
↓イメージすると
pages/
└─ blog/
└─ category/
└─ [slug].jsx ←このページを基準に…
paths: ['blog/category/technology'] ← 相対パス扱い(NG)
paths: ['/blog/category/technology'] ← ルート基準の絶対パス(OK)
3. 推奨される書き方(オブジェクト形式)
動的ページの [slug] に正しく値を渡すには オブジェクト形式の方が安全。
export const getStaticPaths = async () => {
return {
paths: [
{ params: { slug: 'technology' } }, // ←[slug] に対応する値
{ params: { slug: 'business' } },
],
fallback: false,
};
};
params のキー名は ページの動的セグメント名 [slug] と一致させる必要があります。
この方法により、ビルド時に静的ページが正しく生成されます。
4. 文字列形式とオブジェクト形式の仕組みの違い
4-1. 文字列形式
paths: ["/blog/category/technology"]
- Next.js が URL をパースして
[slug]の値を自動的に解釈する - この場合、URL の構造と
[slug]ファイルの位置関係を Next.js が計算している
つまり「Next.js が裏で勝手に params: { slug: "technology" } に変換」しているイメージ。
4-2. オブジェクト形式
paths: [
{ params: { slug: "technology" } }
]
- 開発者が 直接
paramsに値を入れて Next.js に渡す - Next.js はそのまま使うので、パスの解釈をする必要がない
4-3. 同じ挙動になる理由
- 文字列形式は Next.js が URL をパースしてオブジェクト形式に変換している
- オブジェクト形式は 最初から正しい形を渡している
なので、最終的にはどちらも Next.js 内部では params: { slug: "..." } に統一されている。
だから挙動は同じになる。
5. まとめ
- 文字列形式 → Next.js が自動でパースしてオブジェクト化
- 文字列形式で設定する場合は、絶対パスで指定
- オブジェクト形式 → 開発者が直接
paramsを指定(推奨) - 内部的には同じ挙動になるから結果も同じ