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

NextJS 13搭配Mongoose偶现OverwriteModelError问题求助

问题:Next.js 13.4.12 + Mongoose 7.4.2 开发环境下偶现OverwriteModelError

使用Next.js 13.4.12搭配Mongoose 7.4.2开发,浏览器调用RestAPI时偶尔触发OverwriteModelError,提示无法覆盖已编译的useranswer模型。仅在npm run dev模式下出现,npm run build+npm run start生产模式无此问题,且错误并非首次加载出现,需多次刷新页面才会触发。

相关代码片段

1. Difficulty.ts 数据模型定义

import mongoose, { Schema, model, Types } from "mongoose";

const difficultySchema = new Schema({
    name: {
        type: String,
        required: true,
    },
    value: {
        type: Number,
        required: true,
    },
});

export default mongoose.models.Difficulty || model("difficulty", difficultySchema);

2. dbConnect.ts 数据库连接代码

import mongoose, { connect } from "mongoose";

let cached: undefined | Promise<void>;
export default () => {
  if (mongoose.connections && mongoose.connections[0].readyState)
    return Promise.resolve();

  if (!cached) {
    cached = connect(process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/quiz')
      .then(() => console.log("connected to database."))
      .catch((err) => console.log("could not connect to database", err));
  }
  return cached;
}

3. difficulty/page.tsx 页面组件

"use client";

import React from 'react'
import { DataTable } from "primereact/datatable"
import { Column } from "primereact/column"
import { useQuery } from '@tanstack/react-query';
import Link from 'next/link';

export default function Difficulty() {

    const { data: difficultyValues, status: dataFetchStatus, isLoading: isDataLoading } = useQuery({
        queryKey: ["difficulty"],
        queryFn: async () => {
            const res = await fetch(`/api/difficulty`, { cache: "no-cache" });
            return res.json();
        }
    });

    return (
        <>
            <DataTable value={difficultyValues} loading={isDataLoading}>
                <Column field='name' header="Name"></Column>
            </DataTable>
            <Link href="/">Home</Link>
        </>
    )
}

4. api/difficulty/route.ts 接口代码

import Difficulty from "@/app/api/models/Difficulty";
import connection from "@/app/lib/dbConnect";
import { NextResponse } from "next/server";

export async function GET() {
    await connection();
    let result = await Difficulty.find({});
    return NextResponse.json(result);
}

5. UserAnswer.ts 数据模型定义(错误关联但未直接使用)

import mongoose, { Schema, model, Types } from "mongoose";

const userAnswerSchema = new Schema({
    question_answer_id: {
        type: Types.ObjectId,
        required: true,
        ref: 'questionanswer'
    },
    recorded_time: {
        type: Date,
        required: false,
    },
    user_id: {
        type: Types.ObjectId,
        required: true,
        ref: 'user'
    },
    thinkingtime: {
        type: Number,
        required: true,
    },
});

export default mongoose.models.UserAnswer || model("useranswer", userAnswerSchema);;

完整错误信息

[31merror[39m OverwriteModelError: Cannot overwrite `useranswer` model once compiled.
at Mongoose.model (E:\work\integrity\Homeworks\homework4nextjs\node_modules\mongoose\lib\index.js:563:13)
at eval (webpack-internal:///(rsc)/./app/api/models/UserAnswer.ts:28:184)
at (rsc)/./app/api/models/UserAnswer.ts (E:\work\integrity\Homeworks\homework4nextjs\next\server\app\api\question\route.js:82:1)
at __webpack_require__ (E:\work\integrity\Homeworks\homework4nextjs\next\server\webpack-runtime.js:33:42)
at eval (webpack-internal:///(rsc)/./app/api/models/QuestionAnswer.ts:7:69)
at (rsc)/./app/api/models/QuestionAnswer.ts (E:\work\integrity\Homeworks\homework4nextjs\next\server\app\api\question\route.js:72:1)
at __webpack_require__ (E:\work\integrity\Homeworks\homework4nextjs\next\server\webpack-runtime.js:33:42)
at eval (webpack-internal:///(rsc)/./app/api/models/Question.ts:7:73)
at (rsc)/./app/api/models/Question.ts (E:\work\integrity\Homeworks\homework4nextjs\next\server\app\api\question\route.js:62:1)
at __webpack_require__ (E:\work\integrity\Homeworks\homework4nextjs\next\server\webpack-runtime.js:33:42)
at eval (webpack-internal:///(rsc)/./app/api/question/route.ts:5:82)
at (rsc)/./app/api/question/route.ts (E:\work\integrity\Homeworks\homework4nextjs\next\server\app\api\question\route.js:92:1)
at __webpack_require__ (E:\work\integrity\Homeworks\homework4nextjs\next\server\webpack-runtime.js:33:42)
at eval (webpack-internal:///(rsc)/./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?name=app%2Fapi%2Fquestion%2Froute&page=%2Fapi%2Fquestion%2Froute&appPaths=&pagePath=private-next-app-dir%2Fapi%2Fquestion%2Froute.ts&appDir=E%3A%5Cwork%5Cintegrity%5CHomeworks%5Chomework4nextjs%5Capp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=E%3A%5Cwork%5Cintegrity%5CHomeworks%5Chomework4nextjs&isDev=true&tsconfigPath=tsconfig.json&basePath=&assetPrefix=&nextConfigOutput=&preferredRegion=&middlewareConfig=e30%3D!:16:126)
at (rsc)/./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?name=app%2Fapi%2Fquestion%2Froute&page=%2Fapi%2Fquestion%2Froute&appPaths=&pagePath=private-next-app-dir%2Fapi%2Fquestion%2Froute.ts&appDir=E%3A%5Cwork%5Cintegrity%5CHomeworks%5Chomework4nextjs%5Capp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=E%3A%5Cwork%5Cintegrity%5CHomeworks%5Chomework4nextjs&isDev=true&tsconfigPath=tsconfig.json&basePath=&assetPrefix=&nextConfigOutput=&preferredRegion=&middlewareConfig=e30%3D!
(E:\work\integrity\Homeworks\homework4nextjs\next\server\app\api\question\route.js:42:1)
at __webpack_require__ (E:\work\integrity\Homeworks\homework4nextjs\next\server\webpack-runtime.js:33:42)
at __webpack_exec__ (E:\work\integrity\Homeworks\homework4nextjs\next\server\app\api\question\route.js:692:39)
at E:\work\integrity\Homeworks\homework4nextjs\next\server\app\api\question\route.js:693:28
at Object. (E:\work\integrity\Homeworks\homework4nextjs\next\server\app\api\question\route.js:696:3)
at Module._compile (e:\work\integrity\Homeworks\homework4nextjs\lib\internal\modules\cjs\loader.js:1255:14)
at Module._extensions..js (e:\work\integrity\Homeworks\homework4nextjs\lib\internal\modules\cjs\loader.js:1309:10)
at Module.load (e:\work\integrity\Homeworks\homework4nextjs\lib\internal\modules\cjs\loader.js:1113:32)
at Module._load (e:\work\integrity\Homeworks\homework4nextjs\lib\internal\modules\cjs\loader.js:960:12)
at Module.require (e:\work\integrity\Homeworks\homework4nextjs\lib\internal\modules\cjs\loader.js:1137:19)
at require (e:\work\integrity\Homeworks\homework4nextjs\lib\internal\modules\helpers.js:121:18)
at requirePage (e:\work\integrity\Homeworks\homework4nextjs\node_modules\next\dist\server\require.js:112:75)
at e:\work\integrity\Homeworks\homework4nextjs\node_modules\next\dist\server\load-components.js:80:84
at process.processTicksAndRejections (e:\work\integrity\Homeworks\homework4nextjs\lib\internal\process\task_queues.js:95:5)
at async loadComponentsImpl (e:\work\integrity\Homeworks\homework4nextjs\node_modules\next\dist\server\load-components.js:80:26)
at async DevServer.findPageComponentsImpl (E:\work\integrity\Homeworks\homework4nextjs\node_modules\next\dist\server\next-server.js:434:36)
{name: 'OverwriteModelError', digest: undefined, stack:
'OverwriteModelError: Cannot overwrite
`useran…dules\next\dist\server\next-server.js:434:36)', message: 'Cannot overwrite `useranswer` model once compiled.',
Symbol(NextjsError): 'server'}

解决方案

核心原因

开发环境下Next.js的热重载机制会重复加载模块,而模型定义中检查已注册模型的键名与实际注册名称不匹配:

  • 注册UserAnswer模型时使用model("useranswer", userAnswerSchema),模型名称为小写的useranswer
  • 但检查时用了mongoose.models.UserAnswer(驼峰命名),该键不存在于mongoose.models中,导致每次热重载都会重新调用model()方法,尝试覆盖已编译的模型,触发错误。
  • 同样问题也存在于Difficulty.ts中,只是暂时未触发明显错误。

修复步骤

修改所有模型文件,确保检查已注册模型时使用的键名与model()方法中传入的名称完全一致:

修改 UserAnswer.ts

import mongoose, { Schema, model, Types } from "mongoose";

const userAnswerSchema = new Schema({
    question_answer_id: {
        type: Types.ObjectId,
        required: true,
        ref: 'questionanswer'
    },
    recorded_time: {
        type: Date,
        required: false,
    },
    user_id: {
        type: Types.ObjectId,
        required: true,
        ref: 'user'
    },
    thinkingtime: {
        type: Number,
        required: true,
    },
});

// 改为与注册名称一致的小写键名
export default mongoose.models.useranswer || model("useranswer", userAnswerSchema);

修改 Difficulty.ts

import mongoose, { Schema, model, Types } from "mongoose";

const difficultySchema = new Schema({
    name: {
        type: String,
        required: true,
    },
    value: {
        type: Number,
        required: true,
    },
});

// 改为与注册名称一致的小写键名
export default mongoose.models.difficulty || model("difficulty", difficultySchema);

额外说明

生产环境下不会出现该问题,是因为npm run build会将代码打包为静态文件,模块只会加载一次,不会触发重复注册模型的情况。而开发环境的热重载会多次加载模块,暴露了键名不匹配的问题。

内容的提问来源于stack exchange,提问作者Papp Zoltán

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 06:17:04