You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 13中notFound()返回200而非404的问题排查

Next.js动态路由notFound()返回200状态码的问题解析与解决

问题原因拆解

当设置export const dynamicParams = false;时,未预生成的路径会直接触发Next.js的静态404处理,服务器直接返回404状态码并渲染not-found.tsx。但移除该配置后进入SSR模式,出现状态码异常的核心原因通常有两个:

  • notFound()调用时机在客户端:如果资源检查逻辑放在带'use client'指令的客户端组件中,或是通过useEffect等客户端钩子执行,服务器在渲染时已经返回了200状态码的HTML,客户端hydration阶段才触发notFound()切换到404组件,导致网络面板显示200。
  • 服务器端未正确触发状态码:App Router中,notFound()只有在服务器组件或服务器路由处理函数(如route.ts)中调用时,才会让服务器返回404状态码。若检查逻辑仅在客户端执行,服务器无法感知资源不存在,自然返回200。

解决方法

  1. 将检查逻辑移至服务器组件
    把资源存在性检查和notFound()调用放在无'use client'指令的服务器组件中,确保服务器在渲染阶段就能检测到资源不存在,主动返回404状态码:

    // app/[...slug]/page.tsx(服务器组件)
    import { notFound } from 'next/navigation';
    import { getResourceBySlug } from '@/lib/api';
    
    export default async function SlugPage({ params }: { params: { slug: string[] } }) {
      const resource = await getResourceBySlug(params.slug.join('/'));
      if (!resource) {
        notFound(); // 服务器端调用,自动返回404状态码
      }
      return <div>{resource.content}</div>;
    }
    
  2. 通过服务器路由处理函数强制返回404
    如果需要在路由层面统一处理,可在app/[...slug]/route.ts中添加服务器端检查:

    // app/[...slug]/route.ts
    import { notFound } from 'next/server';
    import { checkResourceExists } from '@/lib/utils';
    
    export async function GET(request: Request, { params }: { params: { slug: string[] } }) {
      const exists = await checkResourceExists(params.slug.join('/'));
      if (!exists) {
        notFound(); // 触发404状态码
      }
      // 资源存在时,返回正常响应(或交由page组件处理)
      return new Response(null, { status: 200 });
    }
    
  3. 排查中间件干扰
    检查项目中的middleware.ts,确认没有自定义逻辑错误地覆盖了响应状态码,比如将404响应强制改为200的情况。

关键说明

Next.js的notFound()函数本身会自动设置404状态码,但仅在服务器端执行上下文中生效。如果是在客户端调用,只是前端组件的切换,不会改变服务器已经返回的初始响应状态码。

内容的提问来源于stack exchange,提问作者Maciej Wira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 10:42:54