本文へ移動
verified onnext@16.3.5react@19
最終検証日 2026-09-26
Next.js道場

redirect が効かない(NEXT_REDIRECT)の直し方

実際に出るエラー

Error: NEXT_REDIRECT

redirect を try で囲むと、移動せずに catch へ落ちて Error: NEXT_REDIRECT を受け取ります。

何が起きているか

redirect は、呼んだその場で例外を投げて処理を止めます。Next.js はその例外を受け取って、移動先を返します。

try で囲むと、Next.js より先に自分の catch がその例外を受け取ります。

import { redirect } from 'next/navigation'
 
export default async function Page() {
  try {
    const user = await getUser()
    if (!user) redirect('/login')   // ← ここで例外が投げられる
    return <p>ようこそ</p>
  } catch (e) {
    // ← 移動の合図がここに届いてしまう
    return <p>読み込みに失敗しました: {String(e)}</p>
  }
}

実機で確かめました。ページは 200 で表示され、移動しません。画面には「読み込みに失敗しました: Error: NEXT_REDIRECT」と出ます。

移動の合図が、Next.js に届く前に拾われる
  1. Server
    redirect('/login') を呼ぶ

    移動先を載せた例外を投げる。

  2. Server
    自分の catch が受け取る

    try で囲んでいると、Next.js より先にここへ来る。

  3. Server
    catch が画面を返す

    Next.js は移動の合図を受け取れない。200 で失敗の画面が出る。

受け取った例外の digest には、移動先がそのまま入っていました(実機で NEXT_REDIRECT;replace;/b;307;)。Next.js はこれを見て移動させています。

直し方

書き方ごとの結果(実機で確かめた)
書き方結果
try の中で呼び、catch で画面を返す200。移動しない。catch の画面が出る
redirect を try の外で呼ぶ307 で /login へ移動する
catch の先頭で unstable_rethrow(e)307 で /login へ移動する

1. redirect を try の外に出す(まずこれ)

失敗しうる処理だけを try で囲み、判定と移動は外でします。

export default async function Page() {
  let user
  try {
    user = await getUser()
  } catch {
    return <p>読み込みに失敗しました</p>
  }
 
  if (!user) redirect('/login')   // ← try の外
  return <p>ようこそ</p>
}

公式ドキュメントも、try を使うときは redirect をその外で呼ぶよう書いています。

2. catch の先頭で unstable_rethrow を呼ぶ

構造上、try の中で呼ぶしかないときの方法です。

import { redirect, unstable_rethrow } from 'next/navigation'
 
// ...
  } catch (e) {
    unstable_rethrow(e)   // ← Next.js の合図なら投げ直す
    return <p>読み込みに失敗しました</p>
  }

unstable_rethrow は、受け取った例外が Next.js の合図なら投げ直し、そうでなければ何もしません。本当の失敗だけが catch の残りに進みます。

同じ作りのもの

公式ドキュメントによると、notFound と permanentRedirect も同じく例外を投げてNext.js に伝える作りです。try で囲むと同じように catch に拾われます。unstable_rethrow はこれらもまとめて投げ直します。

直したあとに確かめること

  1. ログインしていない状態で開き、アドレスが /login に変わるかを見る
  2. 開発ツールのネットワークで、最初の応答が 307 になっているかを見る
  3. 取得を本当に失敗させたときに、失敗の画面が出るかを見る(catch を消していないか)

出典

このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。

理解できたか試す

では、このコードはどうなりますか。

ログインしていない人を /login に送りたいページです。ユーザーの取得は失敗することがあるので、try で囲みました。ログインしていない人が開くと、どうなりますか。

この問題を解くこのテーマの問題 3 問