Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return ValidationError from post findOneAndUpdate middleware does not contain message #6171

Closed
jeremyml opened this issue Feb 24, 2018 · 3 comments
Labels
help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary

Comments

@jeremyml
Copy link

@vkarpov15 suggested the code below in this comment

schema.post('findOneAndUpdate', (result, next) =>{
  if (result.docField == 'invalidValue'){
    return next(new mongoose.Error.ValidationError('docField had an invalid value'));
  }
  // ...
});

But the ValidationError does not contain the custom message

docField had an invalid value

Instead the message is simply the canned message

Validation failed

This is the ValidationError in string from:

{
	"errors": {},
	"_message": "Validation failed",
	"message": "Validation failed",
	"name": "ValidationError"
}

I tested it in v 4.13.8 and v 5.0.7

@lineus
Copy link
Collaborator

lineus commented Feb 26, 2018

hi @jeremyml. From what I can tell, it looks like @vkarpov15 was just helping with the async portion of the hook you suggested. After looking at the source for ValidationError, it would appear that if you give it a string instead of an instance of a model, your message will only ever be 'Validation failed'

function ValidationError(instance) {
  this.errors = {};
  this._message = '';
  if (instance && instance.constructor.name === 'model') {
    this._message = instance.constructor.modelName + ' validation failed';
    MongooseError.call(this, this._message);
  } else {
    this._message = 'Validation failed';
    MongooseError.call(this, this._message);
  }
  this.name = 'ValidationError';
  if (Error.captureStackTrace) {
    Error.captureStackTrace(this);
  } else {
    this.stack = new Error().stack;
  }
  if (instance) {
    instance.errors = this.errors;
  }
}

@lineus
Copy link
Collaborator

lineus commented Feb 26, 2018

If you can live with an instance of Error the following works:

#!/usr/bin/env node
'use strict'

const mongoose = require('../lib/test_db')
const Schema = mongoose.Schema

const testSchema = Schema({
  docField: String
})

testSchema.post('findOneAndUpdate', (result, next) => {
  let err = new Error('invalid docfield value')
  err.name = 'ValidationError'
  
  if (result.docField === 'invalidValue') {
    return next(err)
  }
})

const Test = mongoose.model('test', testSchema)

const test = new Test({
  docField: 'valid'
})

let savedDoc = test.save()
savedDoc.then(() => {
  Test.findOneAndUpdate({
    _id: test.id
  }, { docField: 'invalidValue' }, { runValidators: true, new: true }, (err, res) => {
    if (err) { return console.error(err) }
    console.log(res)
  })
})

output:

InspiredMacPro:Help lineus$ ./mongoose5/6171/index.js 
{ ValidationError: invalid docfield value
    at Query.testSchema.post (/Users/lineus/dev/Help/mongoose5/6171/index.js:12:25)
    at callMiddlewareFunction (/Users/lineus/dev/Help/mongoose5/node_modules/kareem/index.js:399:23)
    at next (/Users/lineus/dev/Help/mongoose5/node_modules/kareem/index.js:193:9)
    at Kareem.execPost (/Users/lineus/dev/Help/mongoose5/node_modules/kareem/index.js:217:3)
    at _cb (/Users/lineus/dev/Help/mongoose5/node_modules/kareem/index.js:289:15)
    at _init (/Users/lineus/dev/Help/mongoose5/node_modules/mongoose/lib/query.js:2010:5)
    at model.Document.init (/Users/lineus/dev/Help/mongoose5/node_modules/mongoose/lib/document.js:370:5)
    at completeOne (/Users/lineus/dev/Help/mongoose5/node_modules/mongoose/lib/query.js:1996:12)
    at cb (/Users/lineus/dev/Help/mongoose5/node_modules/mongoose/lib/query.js:2368:14)
    at /Users/lineus/dev/Help/mongoose5/node_modules/mongoose/lib/query.js:2454:16
    at /Users/lineus/dev/Help/mongoose5/node_modules/mongoose/lib/utils.js:418:16
    at session.endSession (/Users/lineus/dev/Help/mongoose5/node_modules/mongodb/lib/utils.js:400:74)
    at ClientSession.endSession (/Users/lineus/dev/Help/mongoose5/node_modules/mongodb-core/lib/sessions.js:69:41)
    at args.push (/Users/lineus/dev/Help/mongoose5/node_modules/mongodb/lib/utils.js:397:17)
    at handleCallback (/Users/lineus/dev/Help/mongoose5/node_modules/mongodb/lib/utils.js:128:55)
    at /Users/lineus/dev/Help/mongoose5/node_modules/mongodb/lib/collection.js:2296:12 name: 'ValidationError' }
^C
InspiredMacPro:Help lineus$ 

@vkarpov15
Copy link
Collaborator

@jeremyml you're right, my example was incorrect

schema.post('findOneAndUpdate', (result, next) =>{
  if (result.docField == 'invalidValue'){
    var validationError = new mongoose.Error.ValidationError(null);
    validationError.addError('docField', new mongoose.Error.ValidatorError({ message: 'Invalid' })); 
    return next(validationError);
  }
  // ...
});

A ValidationError is a mapping of paths to ValidatorError instances, so you need to add one of those

@vkarpov15 vkarpov15 added the help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary label Feb 26, 2018
@lineus lineus closed this as completed Apr 29, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary
Projects
None yet
Development

No branches or pull requests

3 participants