Nathan Huber
Nathan Huber

Reputation: 91

Cast to ObjectId failed for value "undefined" at path "_id" for model "User"

I've been stuck on this error for a while now, I've not been able to get it resolved searching Stack and Google. I have a ProfileScreen.js to display a user's profile. But when you click to view the profile I get this error: Cast to ObjectId failed for value "undefined" at path "_id" for model "User". From the searching I've done, I've tried rolling my version of Mongoose back, but that didn't help. Anyone have any ideas?

userRouter.js

import express from 'express';
import expressAsyncHandler from 'express-async-handler';
import bcrypt from 'bcryptjs';
import data from '../data.js';
import User from '../models/userModel.js';
import { generateToken } from '../utils.js';

const userRouter = express.Router();

userRouter.get('/seed', expressAsyncHandler(async (req, res) => {
  // await User.remove({});
  const createdUsers = await User.insertMany(data.users);
  res.send({ createdUsers });
}));

userRouter.post('/signin', expressAsyncHandler(async (req, res) => {
  const user = await User.findOne({ email: req.body.email });
  if(user) {
    if(bcrypt.compareSync(req.body.password, user.password)) {
      res.send({
        id: user._id,
        name: user.name,
        email: user.email,
        isAdmin: user.isAdmin,
        token: generateToken(user),
      });
      return;
    }
  }
  res.status(401).send({ message: 'Invalid email or password' });
}));

userRouter.post('/register', expressAsyncHandler(async(req, res) => {
  const user = new User({name: req.body.name, email: req.body.email,
    password: bcrypt.hashSync(req.body.password, 8),
  });
  const createdUser = await user.save();
  res.send({
    id: createdUser._id,
    name: createdUser.name,
    email: createdUser.email,
    isAdmin: createdUser.isAdmin,
    token: generateToken(createdUser),
  })
})
);

userRouter.get(
  '/:id',
  expressAsyncHandler(async (req, res) => {
    const user = await User.findById(req.params.id);
    if (user) {
      res.send(user);
    } else {
      res.status(404).send({ message: 'User Not Found' });
    }
  })
);

export default userRouter;

ProfileScreen.js

import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { detailsUser } from '../actions/userActions';
import LoadingBox from '../components/LoadingBox';
import MessageBox from '../components/MessageBox';

export default function ProfileScreen() {
  const userSignin = useSelector((state) => state.userSignin);
  const { userInfo } = userSignin;
  const userDetails = useSelector((state) => state.userDetails);
  const { loading, error, user } = userDetails;
  const dispatch = useDispatch();
  useEffect(() => {
    dispatch(detailsUser(userInfo._id));
  }, [dispatch, userInfo._id]);
  const submitHandler = (e) => {
    e.preventDefault();
    // dispatch update profile
  };
  
  return (
    <div>
      <form className="form" onSubmit={submitHandler}>
        <div>
          <h1>User Profile</h1>
        </div>
        {loading ? (
          <LoadingBox></LoadingBox>
        ) : error ? (
          <MessageBox variant="danger">{error}</MessageBox>
        ) : (
          <>
            <div>
              <label htmlFor="name">Name</label>
              <input 
                id="name"
                type="text"
                placeholder="Enter name"
                value={user.name}>
                </input>
            </div>
            <div>
              <label htmlFor="email">Email</label>
              <input 
                id="email"
                type="email"
                placeholder="Enter email"
                value={user.email}
               >
                </input>
            </div>
            <div>
              <label htmlFor="password">Password</label>
              <input 
                id="password"
                type="password"
                placeholder="Enter password">
                </input>
            </div>
            <div>
              <label htmlFor="confirmPassword">Confirm Password</label>
              <input 
                id="confirmPassword"
                type="password"
                placeholder="Confirm password"
                >
                </input>
            </div>
            <div>
              <label/>
              <button className="primary" type="submit">Update Profile</button>
            </div>
          </>
          )}
      </form>
    </div>
  )
}

I screwed up and posted the wrong code, I posted the user router code instead of the ProfileScreen code. I've added the ProfileScreen code.

Thanks in advance for ANY help.

-N8

Upvotes: 3

Views: 930

Answers (2)

codemonkey
codemonkey

Reputation: 7915

The issue seems to be right here:

dispatch(detailsUser(userInfo._id));

Which should, according to your user object, look like:

dispatch(detailsUser(userInfo.id));

Since _id is undefined as it does not exist in the object, you end up posting to /undefined instead of /60408c4b912e51879c7c08c4. Hence the error.

Upvotes: 1

codeR developR
codeR developR

Reputation: 497

this error comes when mongoose is not able to cast the req.params.id on this line: const user = await User.findById(req.params.id); to an ObjectId

undefined is not castable, and anyway you won't find any doc with undefined as an _id either. You might want to check if req.params.id is undefined, and then return something based on that.

See here to see what a castable objectId is!

Upvotes: 1

Related Questions