skip to Main Content

I am working on a Node JS and MongoDB project. I need to get the collection name from the MongoDB error.

In the errorResponse.errmsg: ‘E11000 duplicate key error collection: cineflex.movies index: name_1 dup key: { name: "hello" }’,

in the above message we can see the collection name cineflex.movies

I need this collection name in the duplicateErrorHandler function.

MongoDB error is:

 MongoServerError: E11000 duplicate key error collection: cineflex.movies index: name_1 dup key: { name: "hello" }
    at InsertOneOperation.execute (D:RNDNode-JSprocademynode-practicenode_modulesmongodbliboperationsinsert.js:51:19)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async executeOperation (D:RNDNode-JSprocademynode-practicenode_modulesmongodbliboperationsexecute_operation.js:136:16)
    at async Collection.insertOne (D:RNDNode-JSprocademynode-practicenode_modulesmongodblibcollection.js:154:16) {
  errorResponse: {
    index: 0,
    code: 11000,
    errmsg: 'E11000 duplicate key error collection: cineflex.movies index: name_1 dup key: { name: "hello" }',
    keyPattern: { name: 1 },
    keyValue: { name: 'hello' }
  },
  index: 0,
  code: 11000,
  keyPattern: { name: 1 },
  keyValue: { name: 'hello' },
  statusCode: 500,
  status: 'error',
  [Symbol(errorLabels)]: Set(0) {}
}

Node JS error controller is

const devErrors = (res, error) => {
    res.status(error.statusCode).json({
        status: error.statusCode,
        message: error.message,
        stackTrace: error.stack,
        error: error
    });
}

const prodErrors = (res, error) => {
    if (error.isOperational) {
        res.status(error.statusCode).json({
            status: error.statusCode,
            message: error.message
        });
    }
    else {
        res.status(500).json({
            status: 'error',
            message: 'Something went wrong! Please try again later.'
        });
    }
}

const castErrorHandler = (err) => {
    const msg = `Invalid value for ${err.path} : ${err.value}`;
    return new CustomError(msg, 400);
}

const duplicateErrorHandler = (err) => { // need collection name for this function
    const name = err.keyValue.name;
    const msg = `There is already a movie with name ${name}. Please use another name.`;
    return new CustomError(msg, 400);
}

module.exports = (error, req, res, next) => {
    error.statusCode = error.statusCode || 500;
    error.status = error.status || 'error';

    console.log('ERROR - ', error);

    if (error.name === "CastError") error = castErrorHandler(error);

    if(error.code === 11000) error = duplicateErrorHandler(error); // need collection name for this function

    if (process.env.NODE_ENV === "development") {
        devErrors(res, error);
    }
    else if (process.env.NODE_ENV === "production") {
        prodErrors(res, error);
    }
}

2

Answers


  1. You can work with Regex to extract the collection name from the errormsg.

    collection: (.*)(?= index)
    

    Capture the value after the "collection: " word and before the " index" word with positive lookahead.

    Demo @ Regex 101

    const duplicateErrorHandler = (err) => { // need collection name for this function
        const name = err.keyValue.name;
    
        const errmsg = err.errmsg;
        const regex = new RegExp('collection: (.*)(?= index)', 'gm');
        let m = regex.exec(str);
    
        const collectionName = m[1];
    
        const msg = `There is already a movie with name ${name}. Please use another name.`;
        return new CustomError(msg, 400);
    }
    
    Login or Signup to reply.
  2. You can change duplicateErrorHandler function:

    const duplicateErrorHandler = (err) => {
    const field = Object.keys(err.keyValue)[0]; // Get the field that caused the duplicate error
    const value = err.keyValue[field]; // Get the value that caused the duplication
    const msg = `There is already a document with the ${field}: "${value}". Please use another value.`;
    return new CustomError(msg, 400);
    

    };

    Now, when the 11000 error is encountered, it will return a message like:

    There is already a document with the name: "hello". Please use another value.
    

    Make sure that CustomError is a valid class or function that creates a custom error with status code and message.

    module.exports = (error, req, res, next) => {
    error.statusCode = error.statusCode || 500;
    error.status = error.status || 'error';
    
    console.log('ERROR - ', error);
    
    // Handle CastError
    if (error.name === "CastError") error = castErrorHandler(error);
    
    // Handle MongoDB Duplicate Key Error
    if (error.code === 11000) error = duplicateErrorHandler(error); 
    
    // Development vs Production Errors
    if (process.env.NODE_ENV === "development") {
        devErrors(res, error);
    }
    else if (process.env.NODE_ENV === "production") {
        prodErrors(res, error);
    }
    

    };

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search