Cast Error for ObjectId for _id

I am having this error every time I try to make request to my api using certain routes that I will share it’s source codes here but for now here is the error I am getting

GET /auth/discord/redirect?code=MsYzdlnjVC6upRhp37LmK5HbFP9IPW 302 7085.898 ms - 64
/Discord Authentication/node_modules/mongoose/lib/schema/objectId.js:250
    throw new CastError('ObjectId', value, this.path, error, this);
          ^
CastError: Cast to ObjectId failed for value "{
  id: {
    discordId: '713145789463134269',
    globalName: 'URIZEN',
    _id: new ObjectId("65536ab9bec76a177731bb99"),
    __v: 0
  }
}" (type Object) at path "_id" for model "User"
    at SchemaObjectId.cast (/Discord Authentication/node_modules/mongoose/lib/schema/objectId.js:250:11)
    at SchemaObjectId.SchemaType.applySetters (/Discord Authentication/node_modules/mongoose/lib/schemaType.js:1219:12)
    at SchemaObjectId.SchemaType.castForQuery (/Discord Authentication/node_modules/mongoose/lib/schemaType.js:1631:15)
    at cast (/Discord Authentication/node_modules/mongoose/lib/cast.js:304:34)
    at model.Query.Query.cast (/Discord Authentication/node_modules/mongoose/lib/query.js:4769:12)
    at model.Query.Query._castConditions (/Discord Authentication/node_modules/mongoose/lib/query.js:2200:10)
    at model.Query._findOne (/Discord Authentication/node_modules/mongoose/lib/query.js:2485:8)
    at model.Query.exec (/Discord Authentication/node_modules/mongoose/lib/query.js:4291:80)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async /Discord Authentication/server.ts:43:16 {
  stringValue: '"{\n' +
    '  id: {\n' +
    "    discordId: '713145789463134269',\n" +
    "    globalName: 'URIZEN',\n" +
    '    _id: new ObjectId("65536ab9bec76a177731bb99"),\n' +
    '    __v: 0\n' +
    '  }\n' +
    '}"',
  messageFormat: undefined,
  kind: 'ObjectId',
  value: {
    id: {
      discordId: '713145789463134269',
      globalName: 'URIZEN',
      _id: [ObjectId],
      __v: 0
    }
  },
  path: '_id',
  reason: BSONError: input must be a 24 character hex string, 12 byte Uint8Array, or an integer
      at new ObjectId (/Discord Authentication/node_modules/bson/src/objectid.ts:80:15)
      at castObjectId (/Discord Authentication/node_modules/mongoose/lib/cast/objectid.js:25:12)
      at SchemaObjectId.cast (/Discord Authentication/node_modules/mongoose/lib/schema/objectId.js:248:12)
      at SchemaObjectId.SchemaType.applySetters (/Discord Authentication/node_modules/mongoose/lib/schemaType.js:1219:12)
      at SchemaObjectId.SchemaType.castForQuery (/Discord Authentication/node_modules/mongoose/lib/schemaType.js:1631:15)
      at cast (/Discord Authentication/node_modules/mongoose/lib/cast.js:304:34)
      at model.Query.Query.cast (/Discord Authentication/node_modules/mongoose/lib/query.js:4769:12)
      at model.Query.Query._castConditions (/Discord Authentication/node_modules/mongoose/lib/query.js:2200:10)
      at model.Query._findOne (/Discord Authentication/node_modules/mongoose/lib/query.js:2485:8)
      at model.Query.exec (/Discord Authentication/node_modules/mongoose/lib/query.js:4291:80),
  valueType: 'Object',

then here is my discord auth for in which I am saving the User Db
//discord-auth.ts

import { Strategy as DiscordStrategy } from 'passport-discord';
import { Data } from "../model/User";

export const createDiscordStrategy = () => {
  const scopes: string[] = ['identify', 'email', 'guilds', 'guilds.join'];

  return new DiscordStrategy({
    clientID:  process.env.DISCORD_CLIENT as string,
    clientSecret: process.env.DISCORD_SECRET as string,
    callbackURL: process.env.CALLBACK,
    scope: scopes
  }, async (accessToken, refreshToken, profile, done) => {
    try {
      const user = await Data.findOne({ discordId: profile.id });

      if (!user) {
        const newUser = new Data({
          discordId: profile.id as string,
          //@ts-ignore
          globalName: profile.global_name as string
        });

        const savedUser = await newUser.save();
        console.log(savedUser);
        done(null, savedUser);
      } else {
        console.log(user); // Log the existing user
        done(null, user);
      }
    } catch (error:any) {
      console.log(error)
      return done(error);
    }
  });
};

then here are my routes for now they are all joined under one file I just want to make it work before i refactor anything what so ever
//server.ts

import express, { Request, Response } from 'express';
import { config } from 'dotenv';
import morgan from 'morgan';
import session = require('express-session');
import passport from 'passport';
import { createDiscordStrategy } from './Authentication/discord-auth';
import { connectDB } from './db/connectDB';
import { Data } from './model/User';
import cors from 'cors';
const MongoDBStore = require('connect-mongodb-session')(session);

config();

const server = express();
const PORT: (string | number) = process.env.PORT || 9000;

server.use(cors());
server.enable('trust proxy');
server.use(express.json());

const store = new MongoDBStore({
  uri:process.env.DATABASE_STRING as string,
  collection: 'sessions',
});

server.use(
  session({
    secret: process.env.JWT_SECRET as string, 
    resave: false,
    saveUninitialized: false,
    store,
    // name:'discord-oauth.id'
  })
);

const discordStrategy = createDiscordStrategy();
passport.use('discord', discordStrategy);
passport.serializeUser((user: any, done) => {
  done(null, user);
});

passport.deserializeUser(async (id: string, done) => {
  const user = await Data.findById({ id });
  if (user) done(null, user);
});

server.use(passport.initialize());
server.use(passport.session());

server.set('view engine', 'ejs');
server.use('/Discord Authentication/public', express.static(__dirname + '/Discord Authentication/public'));
server.use(morgan('dev'));

server.all('/', (req: Request, res: Response) => {
  res.end('Working');
});

server.get('/auth/discord', passport.authenticate('discord'));
server.get('/auth/discord/redirect', passport.authenticate('discord', {
  successRedirect: '/dashboard'
}));

server.get('/dashboard', (req: Request, res: Response) => {
  if (req.user) {
    //@ts-ignore
    const guilds = req.user.guilds.map((guild: { name: string }) => guild.name);
    console.log('Your guilds are: ' + guilds.join(', '));
  } else {
    res.status(401).send('Unauthorized');
  }
});


(async () => {
  
      await connectDB(process.env.DATABASE_STRING as string);
      const app = server.listen(PORT, () => {
        console.log(`Server is running on http://localhost:${PORT}`);
      });

      process.on('SIGINT', () => {
        console.log('Shutting down...');
        app.close(() => {
          console.log('Server closed.');
          process.exit(0);
        });
      });
    } 
  

 
)();

and here is the interface for the modeling of the Schema

import { Document } from "mongoose";

export interface User extends Document {
  discordId: string;
  globalName:string
}

Hi @Akaaha_Victor_Chukwunweike and welcome to MongoDB community forums!!

I see that your post has been unanswered for a long time and I hope you might have resolved the issue.
However if you are still facing the issue, I believe,
The value you’re trying to cast is an object, and Mongoose is expecting it to be a valid ObjectId. In my opinion, since mongoose would directly create the _id value of type ObjectId and hence you can also try skipping to explicitly create the _id field.
You can refer to the official documentation on Mongoose for more details.

There might also be case when the _id being passed, is being not able to parse to ObjectId as it might not be a valid Object.
I tried to replicate the error with the following code:

import mongoose from 'mongoose';
const { Schema } = mongoose;
const ObjectId = mongoose.Types.ObjectId;

const userSchema = new Schema({
  discordId: String,
  globalName: String,
  _id: ObjectId, // Commenting out _id definition to let MongoDB generate it automatically
});

const User = mongoose.model('User', userSchema);

const simulateDiscordAuthentication = async () => {
  try {
    const profile = {
      id: '713145789463134269',
      global_name: 'URIZEN',
      _id: '65536abec7177731bb99'
    };

    const user = await User.findOne({ discordId: profile.id });

    if (!user) {
      const newUser = new User({
        discordId: profile.id,
        globalName: profile.global_name,
        _id: new ObjectId("65536abec7177731bb99") // Simulating the problematic line
      });

      const savedUser = await newUser.save();
      console.log(savedUser);
    } else {
      console.log(user);
    }
  } catch (error) {
    console.error(error);
  }
};
mongoose.connect('mongodb+srv://<userName>:<pass>@sandbox.bl9vn.mongodb.net/?retryWrites=true&w=majority', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

simulateDiscordAuthentication();

and seeing a similar error, BSONError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer

As recommendation you can try adding a validation from the application code, to validate if the _id being passed is a valid object or not.

Please note that, the above has been tested on Mongoose version 7.6.4 and would recommend upgrading to the latest version if you are not already using it.

Finally, in case you still not able to resolve the issue, could you help me with some more error stack trace which would help the community troubleshoot better.

Warm regards
Aasawari