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

Node.js API向MongoDB写入数据时触发必填字段验证报错

问题根因

你遇到的必填字段校验报错,核心原因是服务端没有正确解析到请求体里的JSON参数:
Postman、Thunder Client这类工具发JSON请求时会自动带上Content-Type: application/json请求头,你写的JS测试脚本、Flutter端发请求时默认没加这个头,导致Express的express.json()中间件不会解析请求体,req.body为空对象,解构出来的name/email/password全是undefined,自然触发Mongoose的必填字段校验。

另外你贴的服务端代码本身还有两个会导致异常的硬伤:

  • 拼写错误:bcrypt生成哈希值的变量名是hashedPassword,创建User实例时错写成了hashePassword,少了一个d,就算请求体解析正常,这里也会导致password字段传空。
  • 响应顺序错误:还没执行user.save()存库就提前调用res.json()返回响应,后续数据库操作抛错时无法被路由层捕获,直接触发你看到的UnhandledPromiseRejectionWarning。
修复步骤

1. 修复服务端代码

补全异常捕获、修正拼写错误、调整响应顺序,修复后的参考代码如下:

const DB = "mydburl"
// 补全你自己的依赖引入、端口配置
// const express = require('express')
// const bcryptjs = require('bcryptjs')
// const mongoose = require('mongoose')
// const User = require('./models/User') // 替换为你实际的User模型路径
// const PORT = 3000

const app = express()
app.use(express.json())

app.post('/api/signup', async (req, res) => {
  try {
    const {name, email, password} = req.body
    // 调试阶段可以打开下面这行日志,确认请求体是否正常解析
    // console.log('收到请求体:', req.body)

    const existingUser = await User.findOne({ email })
    if (existingUser) {
      return res.status(400).json({ msg: "同邮箱用户已存在" })
    }

    const hashedPassword = await bcryptjs.hash(password, 8)
    // 修复拼写错误
    let user = new User({
      email,
      password: hashedPassword,
      name,
    })

    // 先执行存库操作,成功后再返回响应
    user = await user.save()
    console.log('用户创建成功:', user)
    return res.json(user)
  } catch (err) {
    // 统一捕获异常,避免出现未处理的Promise拒绝
    console.error('注册接口报错:', err)
    return res.status(500).json({ msg: "服务器处理失败", error: err.message })
  }
}) 

mongoose.connect(DB)
.then(() => console.log("数据库连接成功"))
.catch(e => console.log('数据库连接失败:', e))

app.listen(PORT, "0.0.0.0", () => {
  console.log(`服务启动,监听端口 ${PORT}`)
})

2. 修正客户端请求配置

所有非接口测试工具发起的请求,都需要手动配置JSON请求头:

  • JS测试脚本如果用原生fetch,需要加headers: {'Content-Type': 'application/json'},同时用JSON.stringify()把参数对象转成JSON字符串作为请求体传入;如果用axios,默认会带JSON头,检查下是不是手动改了请求体格式。
  • Flutter端不管用http包还是dio包,都要设置请求头Content-Type: application/json,传参时先将Dart的Map对象通过jsonEncode()转成JSON字符串再放入请求体,不要直接传原生对象。
验证方式

服务端启动后先发起一次测试请求,看控制台打印的请求体日志,如果能正确拿到你传的三个字段值,就说明解析逻辑正常,后续不会再触发必填字段校验报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 07:01:02