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

调用/api/v1/users/login接口报User模型_id的ObjectId转换错误如何修复

问题复现

调用 POST http://localhost:3000/api/v1/users/login 接口时抛出如下错误:

CastError: Cast to ObjectId failed for value "login" at path "_id" for model "User"

报错截图:
报错截图

错误原因

Express 路由遵循从上到下的匹配规则,该错误是因为你将 /login 固定路径路由的定义,放在了带_id动态参数的用户路由(比如GET /:id、PUT /:id这类路由)的后面。当登录请求到达时,会先命中/:id动态路由规则,框架把路径中的login字符串当做_id参数传入,Mongoose 尝试将非ObjectId格式的login转为ObjectId类型失败,因此抛出报错。

修复方案

1. 调整路由定义顺序

将所有固定路径路由的定义,放在动态参数路由的前面即可,示例如下:

// 优先定义固定路径路由
router.post('/login', async (req,res) => {
    const user = await User.findOne({email: req.body.email})
    const secret = process.env.secret;
    if(!user) {
        return res.status(400).send('The user not found');
    }
    if(user && bcrypt.compareSync(req.body.password, user.passwordHash)) {
        const token = jwt.sign(
            {
                userId: user.id,
                isAdmin: user.isAdmin
            },
            secret,
            {expiresIn : '1d'}
        )
        res.status(200).send({user: user.email , token: token}) 
    } else {
       res.status(400).send('password is wrong!');
    }
})

// 动态参数路由放在所有固定路径路由之后定义
router.get('/:id', async (req, res) => {
  // 根据id查询用户的原有逻辑
})
router.put('/:id', async (req, res) => {
  // 更新用户的原有逻辑
})

2. 可选优化:给动态路由加格式校验

可以给动态参数路由增加正则校验,只有参数符合24位十六进制的ObjectId格式时才匹配,避免被错误路径命中:

// 仅id为合法ObjectId格式时才会匹配该路由
router.get('/:id([a-fA-F0-9]{24})', async (req, res) => {
  // 原有逻辑
})

调整完成后重启服务,再次调用登录接口即可正常执行逻辑,不会再触发该报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 04:45:03