You need to enable JavaScript to run this app. Node.js中addFollower方法报hashed_password空值设置错误的排查方案
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中addFollower方法报hashed_password空值设置错误的排查方案

报错核心原因

TypeError: Cannot set property 'hashed_password' of null 的本质是 exec 回调中获取到的 result 值为 null,空对象本身不存在可赋值的属性,因此触发类型错误。结合你的代码链路,触发这个问题的常见场景有三个:

  • User.findByIdAndUpdate 的查询条件不匹配:如果传入的 req.body.followId 在数据库中找不到对应文档,findByIdAndUpdate 默认返回 null,而你没有对返回结果做非空校验,直接执行赋值逻辑就会报错。
  • 路由串行中间件的参数错位:你的 /user/follow 路由依次执行 addFollowing、addFollower 两个中间件,但当前代码完全没有做参数透传,很容易出现 req.body.user_Id、req.body.followId 字段缺失、值格式错误的问题,直接导致Mongoose查询匹配失败。
  • 静默失败没有拦截:findByIdAndUpdate 的配置项没有开启校验规则,就算查询匹配、更新操作出现异常,也不会抛出明确错误,容易让问题隐蔽。
可落地的修复步骤
  1. 回调中补全非空判断,从代码逻辑上杜绝空值赋值
    直接修改 addFollower 方法的回调逻辑,优先校验返回结果的有效性:
    exports.addFollower= (req,res )=>{
        User.findByIdAndUpdate(req.body.followId, {
            $push:{followers: req.body.user_Id}
        },
                {new : true, runValidators: true}
        )
        .populate('following', '_id name')
        .populate('followers', '_id name')
        .exec((err,result)=>{
            if(err){
                return res.status(400).json({
                    error:"关注操作执行失败"
                })
            }
            // 新增非空校验,拦截null场景
            if (!result) {
                return res.status(404).json({
                    error: "要关注的用户不存在,请检查传入的followId"
                })
            }
            result.hashed_password= undefined;
            result.salt = undefined;
            res.json(result)
        })
    }
    
  2. 梳理中间件的参数流转,解决字段缺失问题
    按照关注接口的常规业务逻辑,两个串行中间件的职责是:
    • addFollowing:给当前登录用户的following列表,添加目标关注用户的ID
    • addFollower:给目标关注用户的followers列表,添加当前登录用户的ID
      你现在代码中在addFollower里使用的req.body.user_Id大概率不存在:requireSignin中间件解析token后,一般会把当前登录用户信息挂在req.auth对象上,而不是放在请求体req.body中。如果没有从前端传这个字段,查询时就会因为参数值为undefined匹配不到任何文档,最终返回null。
      调整后的中间件可以通过透传参数的方式,避免依赖不确定的请求体字段:
    // addFollowing 调整后代码
    exports.addFollowing = (req, res, next) => {
        User.findByIdAndUpdate(
            req.auth._id,
            { $push: { following: req.body.followId } },
            { new: true, runValidators: true }
        ).exec(err => {
            if (err) {
                return res.status(400).json({ error: "当前用户的关注列表更新失败" })
            }
            // 把后续需要的参数挂载到req上,透传给下一个中间件
            req.followTargetId = req.body.followId
            req.currentUserId = req.auth._id
            // 进入addFollower中间件
            next()
        })
    }
    
    // addFollower 调整后代码,使用透传的参数
    exports.addFollower = (req, res) => {
        User.findByIdAndUpdate(
            req.followTargetId,
            { $push: { followers: req.currentUserId } },
            { new: true, runValidators: true }
        )
        .populate('following', '_id name')
        .populate('followers', '_id name')
        .exec((err, result) => {
            if (err || !result) {
                return res.status(400).json({ error: "目标用户的粉丝列表更新失败" })
            }
            result.hashed_password = undefined;
            result.salt = undefined;
            res.json(result)
        })
    }
    
  3. 加上快速排查的调试语句
    可以在exec回调的最开头打印两个值,快速定位问题:
    • 打印查询时使用的ID值:确认req.body.followId是不是合法的24位MongoDB ObjectId字符串,有没有出现值为undefined、或者错传成当前登录用户ID的情况
    • 打印回调拿到的err和result内容:如果result为null,就说明数据库中确实找不到对应ID的用户,直接核对ID和数据库记录即可。

额外注意:如果你的userById中间件已经把目标用户信息挂载到了req.profile上,也可以直接复用这个值,不用重新调用findByIdAndUpdate查询,减少重复数据库请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.01 17:54:07