0

I’m working on a MERN stack “to-do list” application which performs CRUD operations. I could successfully implement “adding task to the database” functionality. However, for “removing task” I’m facing with Internal Server Error that I can’t fix although I’ve done research and tried multiple solutions.

I’m sharing related code snippets and I hope someone can help me a bit.

In my client folder, Task.jsx component: *WORKING CODE

function Task({ task }) {
    const { _id, title, description, completed } = task;
    const { dispatch } = useContext(TaskContext);
    const { userToken } = useContext(TokenContext);

    const handleRemove = async (e) => {
        e.preventDefault();
        console.log("Task ID to remove:", _id);
    
        try {
            const res = await axios.get("/task/removeTask", {
                headers: {
                    Authorization: `Bearer ${userToken}`
                },
                params: {
                    _id
                }
            });
            console.log("Task deletion response:", res.data);
            dispatch({
                type: "REMOVE_TASK",
                _id
            });
        } catch (error) {
            console.error("Error removing task:", error);
            // Handle error state or display an error message to the user
        }
    }

taskReducer.js file: *WORKING CODE

function taskReducer(tasks, action) {
    console.log("taskreducer");
    switch (action.type) {
        // eslint-disable-next-line no-lone-blocks
        case "ADD_TASK": {
            return [
                ...tasks,
                {
                    _id: action._id,
                    title: action.title,
                    description: action.description,
                    completed: false
                }
            ]
        }
        case "SET_TASK": {
            return action.payload
        }
        case "REMOVE_TASK": {
            console.log("Tasks before removal:", tasks);
            const updatedTasks = tasks.filter((task) => task._id !== action._id);
            console.log("Tasks after removal:", updatedTasks);
            return updatedTasks;
        }

In my server folder, taskController.js file: *WORKING CODE

import taskModel from "../models/taskModel.js";
import userModel from "../models/userModel.js";
import dotenv from "dotenv";
import mongoose from "mongoose";
dotenv.config();

const addTask = async (req, res) => {
    const { _id, title, description } = req.body;
    const userId = req.user.id;

    const user = await userModel.find({_id: userId});
    if (!user) {
        return res.status(404).json({ message: "User not found" });
    }

    const taskId = _id ? mongoose.Types.ObjectId(_id) : new mongoose.Types.ObjectId();

    console.log("Task to be saved:", { taskId, title, description, completed: false, userId });

    const newTask = new taskModel({ _id: taskId, title, description, completed: false, userId })

    newTask.save()
        .then((savedTask) => {
            return (res.status(200).json({ message: "Task added successfully", task: savedTask }))
        })
        .catch((error) => {
            return (
                res.status(500).json({ message: error.message })
            )
        }
        )
}

const removeTask = (req, res) => {
    const { _id } = req.query;

    console.log("Task ID to remove:", _id); // Log the ID being used for deletion

    taskModel.findByIdAndDelete( _id )
        .then((deletedTask) => {
            if (!deletedTask) {
                return res.status(404).json({ message: "Task not found" });
            }
            console.log("Deleted task:", deletedTask); // Log the deleted task
            return res.status(200).json({ message: "Task deleted successfully" });
        })
        .catch((error) => {
            console.error("Error deleting task:", error); // Log any errors
            return res.status(500).json({ message: "Internal server error" });
        });
}

const getTask = (req, res) => {
    taskModel.find({ userId: req.user.id })
        .lean() // Convert Mongoose documents to plain JavaScript objects
        .then((data) => res.status(200).json(data))
        .catch((error) => res.status(501).json({ message: error.message }))
}

export { addTask, getTask, removeTask }

taskRoute.js file: *WORKING CODE

router.post("/addTask", requireAuth, addTask)
router.get("/getTask", requireAuth, getTask)
router.get("/removeTask", requireAuth, removeTask)

Only removeTask function doesn’t work.

When I add a task, this is the response I’m getting on my browser console:

XHR OPTIONS http://localhost:8000/api/task/addTask[HTTP/1.1 204 No Content 6ms]
XHR POST http://localhost:8000/api/task/addTask[HTTP/1.1 200 OK 468ms]

When I click on the delete button to remove a task, this is the response:

Task ID to remove: 662e7dc365cc6fb9a0e14ed7 // matches the database
XHR OPTIONS http://localhost:8000/api/task/removeTask[HTTP/1.1 204 No Content 10ms]
XHR GET http://localhost:8000/api/task/removeTask[HTTP/1.1 500 Internal Server Error 1ms]
Error removing task: message: “Request failed with status code 500”, name: “AxiosError”, code: “ERR_BAD_RESPONSE”, config: {…}, request: XMLHttpRequest, response: {…} }

​I’ve also tried router.delete("/removeTask") and axios.delete("/task/removeTask") instead of GET method but nothing changed.

I hope you can enlight me a bit about the issue because I’m stucked up on this for a couple of days. Thanks.

EDIT:

Error removing task: 
Object { stack: "AxiosError@http://localhost:3000/static/js/bundle.js:64350:18
settle@http://localhost:3000/static/js/bundle.js:65001:12
onloadend@http://localhost:3000/static/js/bundle.js:63696:66
EventHandlerNonNull*dispatchXhrRequest@http://localhost:3000/static/js/bundle.js:63709:7
./node_modules/axios/lib/adapters/xhr.js/__WEBPACK_DEFAULT_EXPORT__<@http://localhost:3000/static/js/bundle.js:63651:10
dispatchRequest@http://localhost:3000/static/js/bundle.js:64830:10
request@http://localhost:3000/static/js/bundle.js:64267:77
./node_modules/axios/lib/core/Axios.js/forEachMethodNoData/Axios.prototype[method]@http://localhost:3000/static/js/bundle.js:64289:17
wrap@http://localhost:3000/static/js/bundle.js:65402:15
handleRemove@http://localhost:3000/static/js/bundle.js:1828:81
callCallback@http://localhost:3000/static/js/bundle.js:29974:18
invokeGuardedCallbackDev@http://localhost:3000/static/js/bundle.js:30018:20
invokeGuardedCallback@http://localhost:3000/static/js/bundle.js:30075:35
invokeGuardedCallbackAndCatchFirstError@http://localhost:3000/static/js/bundle.js:30089:29
executeDispatch@http://localhost:3000/static/js/bundle.js:34233:46
processDispatchQueueItemsInOrder@http://localhost:3000/static/js/bundle.js:34259:26
processDispatchQueue@http://localhost:3000/static/js/bundle.js:34270:41
dispatchEventsForPlugins@http://localhost:3000/static/js/bundle.js:34279:27
./node_modules/react-dom/cjs/react-dom.development.js/dispatchEventForPluginEventSystem/<@http://localhost:3000/static/js/bundle.js:34439:16
batchedUpdates$1@http://localhost:3000/static/js/bundle.js:48831:16
batchedUpdates@http://localhost:3000/static/js/bundle.js:29822:16
dispatchEventForPluginEventSystem@http://localhost:3000/static/js/bundle.js:34438:21
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay@http://localhost:3000/static/js/bundle.js:31944:42
dispatchEvent@http://localhost:3000/static/js/bundle.js:31938:88
dispatchDiscreteEvent@http://localhost:3000/static/js/bundle.js:31915:22
EventListener.handleEvent*addEventBubbleListener@http://localhost:3000/static/js/bundle.js:32137:14
addTrappedEventListener@http://localhost:3000/static/js/bundle.js:34361:33
listenToNativeEvent@http://localhost:3000/static/js/bundle.js:34305:30
./node_modules/react-dom/cjs/react-dom.development.js/listenToAllSupportedEvents/<@http://localhost:3000/static/js/bundle.js:34316:34
listenToAllSupportedEvents@http://localhost:3000/static/js/bundle.js:34311:25
createRoot@http://localhost:3000/static/js/bundle.js:51594:33
createRoot$1@http://localhost:3000/static/js/bundle.js:51940:14
./node_modules/react-dom/client.js/exports.createRoot@http://localhost:3000/static/js/bundle.js:52016:16
./src/index.js@http://localhost:3000/static/js/bundle.js:2227:60
options.factory@http://localhost:3000/static/js/bundle.js:68791:31
__webpack_require__@http://localhost:3000/static/js/bundle.js:68237:33
@http://localhost:3000/static/js/bundle.js:69373:56
@http://localhost:3000/static/js/bundle.js:69375:12
", 
message: "Request failed with status code 500", 
name: "AxiosError", 
code: "ERR_BAD_RESPONSE", 
config: {…}, 
request: XMLHttpRequest, 
response: {…} 
}

EDIT #2:

I've removed requireAuth from router.get("/removeTask", requireAuth, removeTask) in taskRoute.js file. My server console logs are back.

Here is the full error log on my browser console:

Task ID to remove: 662e7dc365cc6fb9a0e14ed7 Task.jsx:14

XHR OPTIONS http://localhost:8000/api/task/removeTask?_id=662e7dc365cc6fb9a0e14ed7 [HTTP/1.1 204 No Content 9ms]

XHR GET http://localhost:8000/api/task/removeTask?_id=662e7dc365cc6fb9a0e14ed7 [HTTP/1.1 500 Internal Server Error 25ms]

Error removing task: 
Object { stack: "AxiosError@http://localhost:3000/static/js/bundle.js:64350:18\nsettle@http://localhost:3000/static/js/bundle.js:65001:12\nonloadend@http://localhost:3000/static/js/bundle.js:63696:66\nEventHandlerNonNull*dispatchXhrRequest@http://localhost:3000/static/js/bundle.js:63709:7\n./node_modules/axios/lib/adapters/xhr.js/__WEBPACK_DEFAULT_EXPORT__<@http://localhost:3000/static/js/bundle.js:63651:10\ndispatchRequest@http://localhost:3000/static/js/bundle.js:64830:10\nrequest@http://localhost:3000/static/js/bundle.js:64267:77\n./node_modules/axios/lib/core/Axios.js/forEachMethodNoData/Axios.prototype[method]@http://localhost:3000/static/js/bundle.js:64289:17\nwrap@http://localhost:3000/static/js/bundle.js:65402:15\nhandleRemove@http://localhost:3000/static/js/bundle.js:1828:81\ncallCallback@http://localhost:3000/static/js/bundle.js:29974:18\ninvokeGuardedCallbackDev@http://localhost:3000/static/js/bundle.js:30018:20\ninvokeGuardedCallback@http://localhost:3000/static/js/bundle.js:30075:35\ninvokeGuardedCallbackAndCatchFirstError@http://localhost:3000/static/js/bundle.js:30089:29\nexecuteDispatch@http://localhost:3000/static/js/bundle.js:34233:46\nprocessDispatchQueueItemsInOrder@http://localhost:3000/static/js/bundle.js:34259:26\nprocessDispatchQueue@http://localhost:3000/static/js/bundle.js:34270:41\ndispatchEventsForPlugins@http://localhost:3000/static/js/bundle.js:34279:27\n./node_modules/react-dom/cjs/react-dom.development.js/dispatchEventForPluginEventSystem/<@http://localhost:3000/static/js/bundle.js:34439:16\nbatchedUpdates$1@http://localhost:3000/static/js/bundle.js:48831:16\nbatchedUpdates@http://localhost:3000/static/js/bundle.js:29822:16\ndispatchEventForPluginEventSystem@http://localhost:3000/static/js/bundle.js:34438:21\ndispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay@http://localhost:3000/static/js/bundle.js:31944:42\ndispatchEvent@http://localhost:3000/static/js/bundle.js:31938:88\ndispatchDiscreteEvent@http://localhost:3000/static/js/bundle.js:31915:22\n", 
message: "Request failed with status code 500", 
name: "AxiosError", 
code: "ERR_BAD_RESPONSE", 
config: {…}, 
request: XMLHttpRequest, 
response: {…} }

Here is the full error log on my server console:

Task ID to remove: undefined
Error deleting task: CastError: Cast to ObjectId failed for value "{ _id: undefined }" (type Object) at path "_id" for model "Task"
    at model.Query.exec (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\mongoose\lib\query.js:4913:21)
    at Query.then (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\mongoose\lib\query.js:5012:15)
    at removeTask (file:///C:/Users/Rumeysa/Downloads/mern-todo-app-master/server-side/controllers/taskController.js:40:10)
    at Layer.handle [as handle_request] (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\express\lib\router\route.js:144:13)
    at Route.dispatch (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\express\lib\router\route.js:114:3)
    at Layer.handle [as handle_request] (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\express\lib\router\layer.js:95:5)
    at C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\express\lib\router\index.js:284:15  
    at Function.process_params (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\express\lib\router\index.js:346:12)
    at next (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\express\lib\router\index.js:280:10) {
  messageFormat: undefined,
  stringValue: '"{ _id: undefined }"',
  kind: 'ObjectId',
  value: { _id: undefined },
  path: '_id',
  reason: BSONTypeError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer
      at new BSONTypeError (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\bson\lib\error.js:41:28)
      at new ObjectId (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\bson\lib\objectid.js:67:23)
      at castObjectId (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\mongoose\lib\cast\objectid.js:25:12)
      at ObjectId.cast (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\mongoose\lib\schema\objectid.js:246:12)
      at SchemaType.applySetters (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\mongoose\lib\schematype.js:1201:12)
      at SchemaType._castForQuery (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\mongoose\lib\schematype.js:1648:15)
      at SchemaType.castForQuery (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\mongoose\lib\schematype.js:1636:15)
      at SchemaType.castForQueryWrapper (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\mongoose\lib\schematype.js:1612:20)
      at cast (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\mongoose\lib\cast.js:293:34)      at Query.cast (C:\Users\Rumeysa\Downloads\mern-todo-app-master\server-side\node_modules\mongoose\lib\query.js:5341:12),
  valueType: 'Object'
}

Here's the schema on MongoDB:

_id: ObjectId('662e7dc365cc6fb9a0e14ed7')
title: "Add TEST data"
description: "Add data"
userId: "6629874938bc9859f2505388"
completed: false
createdAt: 2024-04-28T16:48:03.875+00:00
updatedAt: 2024-04-28T16:48:03.875+00:00
__v: 0

FINAL EDIT:

Please check the answer. I've edited my code above with the current modifications that fixed the errors I encountered. It is how it looks right now while the app is seamlessly working.

14
  • 1
    You are logging _id but then trying to delete using taskId - what value does taskId have at that point? Commented Apr 29, 2024 at 5:18
  • @Joe taskId is supposed to have the value of _id. I've modified taskController.js removeTask function code: const { _id } = req.body; const taskId = _id ? mongoose.Types.ObjectId(_id) : new mongoose.Types.ObjectId(); taskModel.findByIdAndDelete({ _id: taskId }) Now I can see the ID on the request URL but still receiving Internal Server Error GET http://localhost:8000/api/task/removeTask?_id=662e7dc365cc6fb9a0e14ed7 [HTTP/1.1 500 Internal Server Error 2ms] Commented Apr 29, 2024 at 16:52
  • Does that include the message from the caught error? Commented Apr 29, 2024 at 17:03
  • 1
    For testing further, if possible can you please remove requireAuth from the line - router.get("/removeTask", requireAuth, removeTask) and try. Commented May 1, 2024 at 3:15
  • 1
    Thank you for the update. Please try the following two things as well as part of debugging. 1. Please change the statement const { _id } = req.body to const { _id } = req.query; 2. Please change taskModel.findByIdAndDelete({ _id }) to taskModel.findByIdAndDelete( _id ) Commented May 2, 2024 at 7:20

1 Answer 1

0

After EDIT #2 I have modified the following statements as well and "removing task" fuctionality started to seamlessly work.

In taskController.js file:

From const { _id } = req.body to const { _id } = req.query;

From taskModel.findByIdAndDelete({ _id }) to taskModel.findByIdAndDelete( _id )

I also have added requireAuth back to router.get("/removeTask", removeTask) and everything works as expected including server console logs.

Why requireAuth was a problem so far is because I've defined userToken in const res = await axios.get("/task/removeTask", { headers: { Authorization: 'Bearer ${userToken}' }, in Task.js wrong!

I wrote const { userToken } = useContext(TaskContext); while correct statement would be const { userToken } = useContext(TokenContext);

I would like to thank user @we-do-the-best-for-you for helping me to debug the issue and leading me to the solution.

I'm editing all the code in my question post above with correct changes to reveal fixed code that makes the app work.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.