Search code examples
node.jsyup

Yup Validation Error: "password is a required field" Even When oldPassword Not Provided


I'm facing a validation issue with Yup while using ES Modules in my Node.js project. Here’s the schema I'm using:

import * as Yup from 'yup';

const schema = Yup.object().shape({
  name: Yup.string(),
  email: Yup.string().email(),
  oldPassword: Yup.string().min(6),
  password: Yup.string()
    .min(6)
    .when('oldPassword', (oldPassword, field) =>
      oldPassword ? field.required() : field.notRequired(),
    ),
  confirmPassword: Yup.string().when('password', (password, field) =>
    password
      ? field.required().oneOf([Yup.ref('password')])
      : field.notRequired(),
  )
});

Here's the request body I'm sending:

{
  "name": "Amanda",
  "email": "amanda@example.com"
}

But when I validate it using:

try {
  await schema.validate(req.body, { abortEarly: false }); 
} catch (err) {
  return res
    .status(400)
    .json({ error: 'Validation fails', details: err.errors });
}

I get the following error response:

{
  "error": "Validation fails",
  "details": [
    "password is a required field",
    "confirmPassword is a required field"
  ]
}

What I've Tried:

  1. Explicitly marking fields as .notRequired().

  2. Logging req.body to ensure the input matches the expected structure.

  3. Testing the schema independently with the same input.

Additional Context:

  • Node.js version: 22.12.0
  • Yup version: 1.0.0
  • Using ES Modules (type: "module" in package.json).

Am I missing something in my schema definition, or could this be an issue with how Yup handles conditional logic? Any help would be greatly appreciated!


Solution

    • With yup is better to use is with then and otherwise for Conditional Logic this format is more explicit and reliable for handling dependencies in Yup.

    • Avoid Overloading Inline Functions, it’s less clear and might lead to unexpected behaviors when dealing with complex schemas.

    With the following changes the code should work:

    const schema = Yup.object().shape({
      name: Yup.string(),
      email: Yup.string().email(),
      oldPassword: Yup.string().min(6),
      password: Yup.string()
        .min(6, 'Password must be at least 6 characters')
        .when('oldPassword', {
          is: (oldPassword) => !!oldPassword, // Check if oldPassword is truthy
          then: (schema) => schema.required('Password is required'),
          otherwise: (schema) => schema.notRequired(),
        }),
      confirmPassword: Yup.string()
        .when('password', {
          is: (password) => !!password, // Check if password is truthy
          then: (schema) =>
            schema
              .required('Confirm password is required')
              .oneOf([Yup.ref('password')], 'Passwords must match'),
          otherwise: (schema) => schema.notRequired(),
        }),
    });

    I tested it and it works for me!