I basically defined this Model, much like another which doesn't error out; So I am stumped as to why it's not working...
Here is a Minimal, Reproducible Example
Not working:
import mongoose from 'mongoose';
const TokenSchema = new mongoose.Schema({
_userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User' },
token: { type: String, required: true },
createdAt: { type: Date, required: true, default: Date.now, expires: 43200 }
});
export default mongoose.models.Token || mongoose.model('Token', TokenSchema);
Working:
import mongoose from 'mongoose';
import emailValidator from 'email-validator'
import bcrypt from 'bcrypt'
import crypto from 'crypto'
const SALT_ROUNDS = 12;
const UserSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
trim: true,
lowercase: true,
index: { unique: true },
validate: {
validator: emailValidator.validate,
message: props => `${props.value} is not a valid email address!`
}
},
password: {
type: String,
required: true,
trim: true,
index: { unique: true },
minlength: 7,
maxlength: 11
},
roles: [{ type: 'String' }],
isVerified: { type: Boolean, default: false },
passwordResetToken: String,
resetPasswordExpires: Date
},
{
timestamps: true
}
);
UserSchema.pre('save', async function preSave(next) {
const user = this;
if (!user.isModified('password')) return next();
try {
const hash = await bcrypt.hash(user.password, SALT_ROUNDS);
user.password = hash;
return next();
} catch (err) {
return next(err);
}
});
UserSchema.methods.generatePasswordReset = function () {
this.resetPasswordToken = crypto
.randomBytes(20)
.toString('hex');
this.resetPasswordExpires = Date.now() + 3600000; // expires in an hour
};
UserSchema.methodsparePassword = async function parePassword(candidate) {
return bcryptpare(candidate, this.password);
};
export default mongoose.models.User || mongoose.model('User', UserSchema)
Also I'm following this example in the Next.js Examples repo.
Please help! :)
I basically defined this Model, much like another which doesn't error out; So I am stumped as to why it's not working...
Here is a Minimal, Reproducible Example
Not working:
import mongoose from 'mongoose';
const TokenSchema = new mongoose.Schema({
_userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User' },
token: { type: String, required: true },
createdAt: { type: Date, required: true, default: Date.now, expires: 43200 }
});
export default mongoose.models.Token || mongoose.model('Token', TokenSchema);
Working:
import mongoose from 'mongoose';
import emailValidator from 'email-validator'
import bcrypt from 'bcrypt'
import crypto from 'crypto'
const SALT_ROUNDS = 12;
const UserSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
trim: true,
lowercase: true,
index: { unique: true },
validate: {
validator: emailValidator.validate,
message: props => `${props.value} is not a valid email address!`
}
},
password: {
type: String,
required: true,
trim: true,
index: { unique: true },
minlength: 7,
maxlength: 11
},
roles: [{ type: 'String' }],
isVerified: { type: Boolean, default: false },
passwordResetToken: String,
resetPasswordExpires: Date
},
{
timestamps: true
}
);
UserSchema.pre('save', async function preSave(next) {
const user = this;
if (!user.isModified('password')) return next();
try {
const hash = await bcrypt.hash(user.password, SALT_ROUNDS);
user.password = hash;
return next();
} catch (err) {
return next(err);
}
});
UserSchema.methods.generatePasswordReset = function () {
this.resetPasswordToken = crypto
.randomBytes(20)
.toString('hex');
this.resetPasswordExpires = Date.now() + 3600000; // expires in an hour
};
UserSchema.methods.parePassword = async function parePassword(candidate) {
return bcrypt.pare(candidate, this.password);
};
export default mongoose.models.User || mongoose.model('User', UserSchema)
Also I'm following this example in the Next.js Examples repo.
Please help! :)
Share Improve this question asked Sep 24, 2021 at 21:44 Antonio Pavicevac-OrtizAntonio Pavicevac-Ortiz 7,75920 gold badges75 silver badges156 bronze badges 3- Have you solved this issue? I ran into the same one... – andrewnosov Commented Apr 2, 2022 at 6:33
- @andrewnosov Hey, I did—check out my repo, here Let me know if that syntax doesn't work for you. It may be a version thing too. lmk! cheers! – Antonio Pavicevac-Ortiz Commented Apr 2, 2022 at 13:42
- Thanks! I solve my problem by moving the code of the function used directly to the request file. Don't know how this works but the problem was gone. – andrewnosov Commented Apr 2, 2022 at 16:16
5 Answers
Reset to default 2Apparently the TypeError: Cannot read properties of undefined (reading 'Token')
is happening because the code is executing on the client side when it is intended to execute on the server side.
What is really happening is that mongoose has not initiated a connection to the database, and so mongoose.models
is undefined. But the fix isn't to try to initiate a db connection:
I too was having the a similar issue, when I tried to define too many things in the same file, that is... In my case I'm trying to define Typescript interfaces that can be pulled into client-side code, but the mongoose model definitions end up executing as well...
I read that NextJS does a fair bit of work to split up code that gets sent to client-side and what stays on server-side... The developer should keep this in mind and try to split things that relate to client-side and server-side into different files.
In my case, I placed the Interface definitions and my custom Hooks in a different file from the Mongoose Schema definitions; and then imported only the Interfaces and Hooks when I need those, which made the errors go away.
Trying to keep everything in the same place sounds logical and neat, but doesn't work in this case.
I had the same error. Even though my schema file was correct. the issue was for some reason, I have been importing the model in react ponent file
import room from "../models/room";
I had the same error and solved with the following solution:
export default mongoose.models?.User || mongoose.model('User', UserSchema)
I copied your code and it worked fine (went into the tokens
collections versus token
like expected possibly) one thing I noticed was the expires
field on createdAt
- was this a NextJS field? It's not a default field so just curious. Also, can you paste the exact error you are encountering, this will help someone track the issue down.
{
_userId: new ObjectId("5e1a0651741b255ddda996c4"),
token: 'abcd123',
createdAt: 2021-09-24T23:10:24.288Z,
_id: new ObjectId("614e5ae04c741f91ac062530"),
__v: 0
}
Also, consider using the timestamps options property when declaring the model as this will save you the headache of setting createdAt
up (and you can also have updatedAt
automatically update).
token: { type: String, required: true },
},
{
timestamps: true
}
);
the solution is import models in 'use server' ponent. ingshaAllah it will be solve.