使用Sequelize的Model.create创建用户时触发类型错误问题排查
使用Sequelize的Model.create提交用户数据时遇到TypeError: Cannot convert undefined or null to object错误的解决
问题描述
调用Sequelize的Model.create方法创建用户时触发错误:TypeError: Cannot convert undefined or null to object。其他模型的POST、GET路由均正常,已传入nome、login、senha字段(senha_hash通过钩子由senha自动生成),尝试判断传入对象是否为null/undefined但未触发提示,报错依旧。
相关代码文件
迁移文件(usuarios.js)
/** @type {import('sequelize-cli').Migration} */ module.exports = { up: (queryInterface, Sequelize) => queryInterface.createTable('usuarios', { id: { type: Sequelize.INTEGER, autoIncrement: true, allowNull: false, primaryKey: true, }, nome: { type: Sequelize.STRING, allowNull: false, }, login: { type: Sequelize.STRING, allowNull: false, unique: true, }, senha_hash: { type: Sequelize.STRING, allowNull: false, }, created_at: { type: Sequelize.DATE, }, updated_at: { type: Sequelize.DATE, }, }), down: (queryInterface) => queryInterface.dropTable('usuarios'), };
模型文件(Usuario.js)
import Sequelize, { Model } from 'sequelize'; import bcryptjs from 'bcryptjs'; export default class Aluno extends Model { static init(sequelize) { super.init({ nome: { type: Sequelize.STRING, defaultValue: '', validate: { len: { args: [3, 255], msg: 'O nome deve conter de 3 a 255 caracteres.', }, }, }, login: { type: Sequelize.STRING, defaultValue: '', unique: { msg: 'Este nome de usuário já existe.', }, }, senha_hash: { type: Sequelize.STRING, defaultValue: '', }, senha: { type: Sequelize.VIRTUAL, defaultValue: '', validate: { len: { args: [6, 24], msg: 'A senha precisa ter entre 6 e 24.', }, }, }, }, { sequelize, }); this.addHook('beforeSave', (user) => { user.senha_hash = bcryptjs.hash(user.senha, 8); }); return this; } }
控制器文件(UsuarioController.js)
import Usuario from '../models/Usuario'; class UsuarioController { async index(req, res) { const usuarios = await Usuario.findAll(); return res.status(200).json(usuarios); } async store(req, res) { try { const { nome, login, senha } = req.body; const dados = { nome, login, senha }; const novoUsuario = await Usuario.create(dados); // if (dados === null || dados === undefined) { // return res.status(400).json('Dados vazios'); // } return res.status(200).json(novoUsuario); } catch (e) { return null; } } } export default new UsuarioController();
路由文件(usuarioRoutes.js)
import { Router } from 'express'; import usuarioController from '../controllers/UsuarioController'; const router = new Router(); router.post('/', usuarioController.store); router.get('/', usuarioController.index); export default router;
主文件(app.js)
import dotenv from 'dotenv'; dotenv.config(); import './src/database'; import express from 'express'; import homeRoutes from './src/routes/homeRoutes'; import alunoRoutes from './src/routes/alunoRoutes'; import instituicaoRoutes from './src/routes/instituicaoRoutes'; import disciplinaRoutes from './src/routes/disciplinaRoutes'; import turmaRoutes from './src/routes/turmaRoutes'; import usuarioRoutes from './src/routes/usuarioRoutes'; class App { constructor() { this.app = express(); this.middlewares(); this.routes(); } middlewares() { this.app.use(express.urlencoded({ extended: true })); this.app.use(express.json()); } routes() { this.app.use('/', homeRoutes); this.app.use('/alunos', alunoRoutes); this.app.use('/instituicao', instituicaoRoutes); this.app.use('/disciplina', disciplinaRoutes); this.app.use('/turma', turmaRoutes); this.app.use('/usuarios', usuarioRoutes); } } export default new App().app;
错误原因及解决方法
1. 模型类名定义错误
模型文件中定义的类名为Aluno(意为学生),但导出的文件名为Usuario.js,控制器中导入的也是Usuario。类名与导入名称不匹配,导致Sequelize无法正确识别并初始化用户模型,这是核心错误。
修复:
将模型类名改为Usuario:
export default class Usuario extends Model { // ... 原有代码不变 }
2. beforeSave钩子的异步问题与空值处理
bcryptjs.hash是异步方法,直接赋值会导致senha_hash接收的是Promise对象,而非哈希后的字符串;同时如果user.senha为空或未传入,hash方法会接收undefined,触发类型错误。
修复:
改用同步哈希方法hashSync,并增加非空判断:
this.addHook('beforeSave', (user) => { if (user.senha) { user.senha_hash = bcryptjs.hashSync(user.senha, 8); } });
如果要使用异步版本,需将钩子改为异步函数:
this.addHook('beforeSave', async (user) => { if (user.senha) { user.senha_hash = await bcryptjs.hash(user.senha, 8); } });
3. 控制器错误处理与参数校验问题
- 参数校验位置错误:原代码在
create之后判断dados是否为null/undefined,但dados是字面量对象,永远不会为null/undefined,应该在create之前校验字段是否存在。 - 错误捕获后直接返回
null,导致客户端收不到任何响应,应该返回错误信息。
修复:
async store(req, res) { try { const { nome, login, senha } = req.body; if (!nome || !login || !senha) { return res.status(400).json('Dados vazios'); } const dados = { nome, login, senha }; const novoUsuario = await Usuario.create(dados); return res.status(200).json(novoUsuario); } catch (e) { return res.status(400).json({ erro: e.message }); } }
内容的提问来源于stack exchange,提问作者Khiuta
相关产品推荐
相关产品推荐

