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 <-- </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 } ); } }
前端代码优化建议
- 修正接口路径:将
"./api/register"改为"/api/register",避免路由嵌套时的路径解析错误 - 添加错误处理:捕获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
相关产品推荐
相关产品推荐

