I am developing a webapp and using Sequelize to manage my database (Postgres). The User is always found and returns correctly, however finding the Credentials spits out:
TypeError: Cannot convert undefined or null to object
at hasOwnProperty (<anonymous>)
at credentials._paranoidClause (C:\bots\Trion\node_modules\sequelize\lib\model.js:176:65)
at credentials.findAll (C:\bots\Trion\node_modules\sequelize\lib\model.js:1135:20)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async credentials.findOne (C:\bots\Trion\node_modules\sequelize\lib\model.js:1240:12)
at async login (file:///C:/bots/Trion/routes/auth.js:77:21)
Here are my models:
User.js
import { DataTypes } from "sequelize";
import { sequelize } from './SQL.js';
const User = sequelize.define("user", {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false
},
anonymous: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true
},
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
avatarBlob: {
type: DataTypes.BLOB
}
}, {
sequelize,
tableName: "user",
timestamps: true,
createdAt: "createdAt",
updatedAt: false,
deletedAt: "deletedAt",
paranoid: true
});
User.hasOne(Credentials, {
sourceKey: 'id',
foreignKey: 'userId',
onUpdate: 'CASCADE',
onDelete: 'CASCADE'
});
Credentials.belongsTo(User);
export { User };
Credentials.js
import { DataTypes } from "sequelize";
import { sequelize } from './SQL.js';
import { User } from './User.js';
const Credentials = sequelize.define("credentials", {
userId: {
type: DataTypes.INTEGER,
unique: true,
allowNull: false
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
salt: {
type: DataTypes.STRING,
allowNull: false,
}
}, {
sequelize,
tableName: "credentials",
timestamps: true,
createdAt: false,
updatedAt: "updatedAt",
deletedAt: false,
paranoid: true
});
export { Credentials };
These two are 1:1 related, and it works when seen from a GUI client.
Here is the problem code:
let user = await User.findOne({ where: { username: payload.username } });
let creds = await Credentials.findOne({ where: { userId: user.id } });
What may be happening here? Everything looks ok according to the docs, and it's been driving me in circles for a good while now.
I have tried finding it through a raw query, which works as intended:
'SELECT * FROM credentials WHERE credentials."userId" = ' + user.id + ';'
I have also tried some specific Sequelize things, like:
await User.findOne({ where: { username: payload.username }, include: Credentials });
which spits out the same error, or:
await User.getCredentials();
which doesn't exist (but the docs suggest the function should be automatically generated?).
Found the answer myself by deeply debugging Sequelize, and what a silly mistake it was. Please don't disable the deletedAt column on your models if you're gonna leave paranoid mode on.