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

Next.js新App Router中出现TypeError: Cannot read properties of undefined (reading 'headers')求助

Next.js App Router注册接口报错:TypeError: Cannot read properties of undefined (reading 'headers')

遇到的错误信息:

TypeError: Cannot read properties of undefined (reading 'headers')
    at eval (webpack-internal:///(rsc)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:265:61)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

已尝试返回NextResponse.json但错误依旧,以下是更新后的代码:

更新后的后端代码

const bcrypt = require("bcrypt")
const User = require("../../model/userModel")

export async function POST(req: NextRequest) {
  await dbConnect()
  const res = await req.json()
  await bcrypt.hash(res.passwd, 10)
      .then(async (hashedPassword: any) => {
          //create a new user instance and collect the data
          const user = new User({
              firstname: res.firstname,
              lastname: res.lastname,
              company: res.company,
              phone: res.phone,
              email: res.email,
              password: hashedPassword,
          })
          await user.save()
          //return succes if the new user is added to the database
          .then((result: string) => {
              return NextResponse.json({message: "User created successfully "},{status : 201}) 
          })
          .catch((err: string) => {
            console.log("error" + err)
            return NextResponse.json({message: "Error creating user :"},{status : 500}) 
          })
      })
      .catch((err: string) => {
        console.log("error" + err)
        return NextResponse.json({message: "Password was not hashed successfully "},{status : 500})  
      })
}

前端调用代码

async function createUser(ev: any){
        ev.preventDefault()
        const data = {firstname, lastname, company, phone, email, passwd}
        await axios.post("./api/register", data)
    }

    //Email validation
    function isValidEmail(email: string) {
        return /\S+@\S+\.\S+/.test(email);
      }
      

  return (
    <>
        <main className="flex justify-center items-center w-screen min-h-screen bg-[url('../public/bg-login.jpg')] bg-no-repeat bg-cover">
            <div className="flex flex-col w-1/2 h-3/4 rounded-lg shadow-2xl shadow-white m-5">
                <form onSubmit={createUser} className="w-full"> 
                    <div className="grid sm:grid-cols-1 md:grid-cols-2 gap-10 mb-5 mr-5 ml-5 mt-5">
                        <div>
                            <label htmlFor="firstname" className="text-white block mb-2 text-sm font-medium dark:text-white">*First name</label>
                            <input 
                                className="outline-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:border-blue-500 p-2 w-full" 
                                type="text"
                                onChange={ (e) => {
                                setFirstname(e.target.value)
                                }}
                                placeholder="First name"
                                value={firstname} 
                                id="firstname"
                                required/>
                        </div>
                        <div>
                            <label htmlFor="lastname" className="text-white block mb-2 text-sm font-medium dark:text-white">*Last name</label>
                            <input 
                                className="outline-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:border-blue-500 p-2 w-full" 
                                type="text"
                                onChange={ (e) => {
                                setLastname(e.target.value)
                                }}
                                placeholder="Last name"
                                value={lastname} 
                                id="lastname"
                                required/>
                        </div>
                        <div>
                            <label htmlFor="company" className="text-white block mb-2 text-sm font-medium dark:text-white">*Company</label>
                            <input 
                                className="outline-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:border-blue-500 p-2 w-full" 
                                type="text"
                                onChange={ (e) => {
                                setCompany(e.target.value)
                                }}
                                placeholder="Zincometal"
                                value={company} 
                                id="company"
                                required/>
                        </div>
                        <div>
                            <label htmlFor="phone" className="text-white block mb-2 text-sm font-medium dark:text-white">*Phone number</label>
                            <input 
                                className="outline-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:border-blue-500 p-2 w-full" 
                                type="number"
                                onChange={ (e) => 
                                    {  
                                        setPhone(e.target.valueAsNumber)       
                                    }}
                                placeholder="xx-xxx-xxx-xx"
                                value={phone} 
                                id="phone"
                                required/>
                        </div>
                        <div className="md:col-span-2 sm:col-span-1">
                            <label htmlFor="email" className="text-white block mb-2 text-sm font-medium dark:text-white">*Email Address</label>
                            <input 
                                className="outline-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:border-blue-500 p-2 w-full" 
                                type="text"
                                onChange={ (e) => 
                                    {  
                                        if (!isValidEmail(e.target.value)){
                                            setError(true)
                                        }else{
                                            setError(false)
                                        }
                                        setEmail(e.target.value)       
                                    }}
                                placeholder="example@hotmail.com"
                                value={email} 
                                id="email"
                                required/>
                        </div>
                        <div className="md:col-span-2 sm:col-span-1">
                            <label htmlFor="passwd" className="text-white block mb-2 text-sm font-medium dark:text-white">*Password</label>
                            <input 
                                className="outline-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:border-blue-500 p-2 w-full" 
                                type="password"
                                onChange={ (e) => 
                                    {  
                                            setPasswd(e.target.value)       
                                    }}
                                placeholder="*******"
                                value={passwd} 
                                id="passwd"
                                required/>
                        </div>
                        <div className="md:col-span-2 sm:col-span-1">
                            <label htmlFor="confPasswd" className="text-white block mb-2 text-sm font-medium dark:text-white">*Confirm Password</label>
                            <input 
                                className="outline-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:border-blue-500 p-2 w-full" 
                                type="password"
                                onChange={ (e) => 
                                    {  
                                            setConfPasswd(e.target.value)       
                                    }}
                                placeholder="*******"
                                value={confPasswd} 
                                id="confPasswd"
                                required/>
                        </div>
                        <div className="flex items-start">
                            <div className="flex items-center h-6">
                                <input
                                    className="w-4 h-4 border border-gray-300 rounded bg-gray-50 focus:ring-3 focus:ring-blue-300" 
                                    type="checkbox" 
                                    value='' 
                                    id="remember"/>
                            </div>
                            <label htmlFor="remember" className="ml-2 text-sm font-medium text-white">
                                I agree with the <a href="#" className="text-blue-600 hover:underline dark:text-blue-500">terms and conditions</a>.
                            </label>
                            <Link href="./" className="mr-5 mt-5 font-medium text-white text-right hover:underline decoration-solid">
                                Return to login &lt;--
                            </Link>
                            {error && <div>{error}</div>}
                        </div>
                    </div>
                    <button type="submit" className="ml-5 mb-5 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Submit</button>
                </form>
            </div>
        </main>
    </>
  )
}

错误原因与修复方案

核心问题:POST函数未正确返回响应

你的代码中,bcrypt.hash和user.save使用了.then/.catch链式调用,但外层的POST函数没有返回这个Promise链,导致Next.js路由处理无法获取到有效响应对象,从而抛出headers未定义的错误。同时代码混合使用async/await与.then/.catch,逻辑混乱,进一步加剧了返回值丢失的问题。

修复后的后端代码

import { NextRequest, NextResponse } from 'next/server';
import bcrypt from 'bcrypt';
import User from '../../model/userModel';
import dbConnect from '../../path-to-dbConnect'; // 替换为你的dbConnect实际路径

export async function POST(req: NextRequest) {
  try {
    await dbConnect();
    const body = await req.json();
    
    // 哈希密码
    const hashedPassword = await bcrypt.hash(body.passwd, 10);
    
    // 创建用户实例
    const user = new User({
      firstname: body.firstname,
      lastname: body.lastname,
      company: body.company,
      phone: body.phone,
      email: body.email,
      password: hashedPassword,
    });
    
    // 保存用户到数据库
    await user.save();
    
    return NextResponse.json(
      { message: "用户创建成功" },
      { status: 201 }
    );
  } catch (err) {
    console.error("创建用户错误:", err);
    
    // 根据错误类型返回对应提示
    if (err instanceof Error) {
      // 处理重复邮箱的MongoDB错误
      if (err.message.includes('E11000 duplicate key')) {
        return NextResponse.json(
          { message: "该邮箱已被注册" },
          { status: 400 }
        );
      }
      return NextResponse.json(
        { message: `创建用户失败: ${err.message}` },
        { status: 500 }
      );
    }
    
    return NextResponse.json(
      { message: "创建用户失败" },
      { status: 500 }
    );
  }
}

前端代码优化建议

  1. 修正接口路径:将"./api/register"改为"/api/register",避免路由嵌套时的路径解析错误
  2. 添加错误处理:捕获axios请求异常,给用户明确提示
async function createUser(ev: any){
  ev.preventDefault();
  try {
    const data = { firstname, lastname, company, phone, email, passwd };
    const response = await axios.post("/api/register", data);
    alert(response.data.message);
    // 注册成功后可跳转登录页,需先导入useRouter
    // const router = useRouter();
    // router.push("/login");
  } catch (err) {
    console.error("注册失败:", err);
    alert(err.response?.data?.message || "注册失败,请稍后重试");
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 18:04:53