TypeError: Expected string but received a undefined

Viewed 10006

While validating the name and password before posting it to the mongodb database it is showing some errror

const Validator = require('validator');
const isEmpty = require('./is-empty');

module.exports = function validateRegisterInput(data){
    let errors = {};

    data.name = !isEmpty(data.name) ? data.name : '';
    data.email = !isEmpty(data.email) ? data.email : '';
    data.password = !isEmpty(data.password) ? data.password : '';
    data.password = !isEmpty(data.password2) ? data.password2 : '';


    if((!Validator.isLength(data.name , { min:2, max:20 }))){
        errors.name = 'Name must be between 2 and 20 characters';
    }

    if(Validator.isEmpty(data.name)){
        errors.name ='Name field is required';
    }

    if(Validator.isEmpty(data.email)){
        errors.email ='Email field is required';
    }

    if(Validator.isEmail(data.email)){
        errors.email ='Email is invalid';
    }

    if(Validator.isEmpty(data.password)){
        errors.password ='Password field is required';
    }

    if(Validator.isLength(data.password, {min:8 })){
        errors.password ='Password field is required';
    }

    if(Validator.isEmpty(data.password2)){
        errors.password2 ='Confirm Passwords field is required';
    }

    if(Validator.equals(data.password, data.password2)){
        errors.password2 = 'Passwords must match';
    }

    return {
        errors,
        isValid: isEmpty(errors)
    };
};

error showing in postman

TypeError: Expected string but received a undefined.
   at assertString (E:\MERN\devconnector\node_modules\validator\lib\util\assertString.js:28:11)
   at Object.isEmpty (E:\MERN\devconnector\node_modules\validator\lib\isEmpty.js:19:29)
   at validateRegisterInput (E:\MERN\devconnector\validation\register.js:38:18)
   at router.post (E:\MERN\devconnector\routes\api\users.js:27:33)
   at Layer.handle [as handle_request] (E:\MERN\devconnector\node_modules\express\lib\router\layer.js:95:5)
   at next (E:\MERN\devconnector\node_modules\express\lib\router\route.js:137:13)
   at Route.dispatch (E:\MERN\devconnector\node_modules\express\lib\router\route.js:112:3)
   at Layer.handle [as handle_request] (E:\MERN\devconnector\node_modules\express\lib\router\layer.js:95:5)
   at E:\MERN\devconnector\node_modules\express\lib\router\index.js:281:22
   at Function.process_params (E:\MERN\devconnector\node_modules\express\lib\router\index.js:335:12)
   at next (E:\MERN\devconnector\node_modules\express\lib\router\index.js:275:10)
   at Function.handle (E:\MERN\devconnector\node_modules\express\lib\router\index.js:174:3)
   at router (E:\MERN\devconnector\node_modules\express\lib\router\index.js:47:12)
   at Layer.handle [as handle_request] (E:\MERN\devconnector\node_modules\express\lib\router\layer.js:95:5)
   at trim_prefix (E:\MERN\devconnector\node_modules\express\lib\router\index.js:317:13)
   at E:\MERN\devconnector\node_modules\express\lib\router\index.js:284:7
8 Answers

Please check where you declared isEmpty function in your isEmpty.js file, you probably used an arrow function, which shouldn't be.

const isEmpty = value => {
    value === undefined ||
    value === null ||
    (typeof value === "Object" && Object.keys(value).length === 0) ||
    (typeof value === "string" && value.trim().length === 0)

}

So, remove the curly brackets at the end of the arrow function "{}", it shouldn't be there.

try adding this :

data.password**2** = !isEmpty(data.password2) ? data.password2 : ''; 

You must add

if("HERE"Validator.equals(data.password, data.password2)){
        errors.password2 = 'Passwords must match';
}

and change "data.password" to data.password2 in line 10

I recommend to write data in JSON format and then check the content-type which should be application/json. the same issue happened to me and I resolve it the way I mentioned.

If you are writing arrow function with multiple lines then We should have explicit return value or result.

  const isEmpty = value => {
  return (value === undefined ||
    value === null ||
    (typeof value === "Object" && Object.keys(value).length === 0) ||
    (typeof value === "string" && value.trim().length === 0))

};

module.exports = isEmpty;

Note: Please refer ES6 documentation for clarity : http://es6-features.org/

Seeing you using Validator package, I understand what you're trying to achieve as I've just come out of this repetitive TypeErrors that I was getting. I also had some typo's in it which I had to fix. So make sure you don't have any.

In this case I'd write the code in this manner. It's a little verbose and I'd refactor it ASAP, I just got this right now and as I saw this question I would like to give my inputs.

const Validator = require("validator");
const isEmpty = require("./is-empty");
// we cant use isEmpty from validator pkg as it needs its param to be a string

// data is req.body
module.exports = function validateRegisterInput(data) {
    let errors = {};

    data.name = isEmpty(data.name) ? "" : data.name;
    data.email = isEmpty(data.email) ? "" : data.email;
    data.password = isEmpty(data.password) ? "" : data.password;
    data.password2 = isEmpty(data.password2) ? "" : data.password2;

    if (!Validator.isLength(data.name, { min: 2, max: 30 })) {
        errors.name = "Name must be between 2 and 30 characters";
    }

    if (Validator.isEmpty(data.name)) {
        errors.name = "Name field is required";
    }

    if (Validator.isEmpty(data.email)) {
        errors.email = "Email field is required";
    }

    // runs if not in email exists but not in format
    if (!Validator.isEmpty(data.email) && !Validator.isEmail(data.email)) {
        errors.email = "Email is invalid";
    }

    if (Validator.isEmpty(data.password)) {
        errors.password = "Password field is required";
    }

    // runs if password exists but not in proper format
    if (
        !Validator.isEmpty(data.password) &&
        !Validator.isLength(data.password, { min: 6, max: 30 })
    ) {
        errors.password = "Password must be at least 6 chracters";
    }

    if (Validator.isEmpty(data.password2)) {
        errors.password2 = "Password 2 is required";
    }

    // runs if not in password 2 exists but not in format
    if (
        !Validator.isEmpty(data.password2) &&
        !Validator.equals(data.password, data.password2)
    ) {
        errors.password2 = "Passwords must match";
    }

    return { errors, isValid: isEmpty(errors) };
};

I faced the same problem and I fixed it by checking if the fields are not (isEmpty) before checking (isEmail, isLength, ...)

for example:

if (!Validator.isLength(data.name, { min: 2, max: 30 })) {
  errors.name = "Name must be between 2 and 30 characters"
}

becomes:

if (
    !Validator.isEmpty(data.name) &&
    !Validator.isLength(data.name, { min: 2, max: 30 })
) {
    errors.name = "Name must be between 2 and 30 characters";
}

Something similar happened to me. I was validating a key called 'name', but on postman I was sending 'username'.

Double check that your keys in postman exactly match your data.whatever

Related