yup: yup.number().nullable() does not allow `null` value

const quantity = number().positive().nullable(); does not work for me in case of quantity:null this input gives me this error

quantity must be a number type, but the final value was: NaN (cast from the value NaN). ValidationError: quantity must be a number type, but the final value was: NaN (cast from the value NaN).

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 12
  • Comments: 22 (1 by maintainers)

Most upvoted comments

Hey, you must pass a boolean value as argument to nullable

const quantity = number().positive().nullable(true);
.transform(v => v === '' ? null : v)

I used:

.transform((v, o) => o === '' ? null : v)

…after noting that transform supplies two arguments to the callback, the second being the originalValue which was the empty string for me.

I tried using the following parameters/properties on yup so that the ‘year’, ‘month’, and ‘day’ are optional. However, it keeps giving an error message.

year: yup
        .number()
        .nullable(true),
    month: yup
        .number()
        .min(1)
        .max(12)
        .positive()
        .nullable(true)
        .transform(v => v === '' ? null : v),
    day: yup
        .number()
        .min(1)
        .max(31)
        .positive()
        .nullable(true)
        .transform(v => v === '' ? null : v),
Screen Shot 2021-04-11 at 2 24 18 AM

I solved this problem like this:

number()
    .transform((currentValue, originalValue) => {
        return originalValue === '' ? null : currentValue;
    })
    .nullable()
    .typeError('Must be a number')

Hi guys,

Why is this issue closed.

The simple fact that clearing an input field with type="number" should not throw an “Invalid value” message as @simoami showed.

Why should we have to use a transform method to fix this everytime we have a number field ?

I have the same problem. nullable() is the same as nullable(true), so that’s not the solution.

So is this going to be fixed/changed? null, undefined, NaN should trigger the validation only if nullable(false) or required() is present … and i would like to avoid adding that transform to each number input…

.transform(v => v === '' ? null : v)

I used:

.transform((v, o) => o === '' ? null : v)

…after noting that transform supplies two arguments to the callback, the second being the originalValue which was the empty string for me.

Also validating the NaN in case of numeric inputs

.transform((v) => (v === '' || Number.isNaN(v) ? null : v))
quantity = number().positive().nullable()
quantity.validateSync(null) // No error

quantity = number().positive().nullable(false)
quantity.validateSync(null) // Error

If you check the original validation error, it has a property called params which should contain something like:

  params:
   { path: 'this', // or e.g 'someNestedObj.quantity`
     value: NaN, // <<<<<<<<<< when cast to number
     originalValue: null, // <<<<<<<<<< before cast to number (original)
     label: undefined,
     type: 'number' }

originalValue should contain the original … value that was passed before Yup tried to cast it to number. Are you sure that what you’re passing (as originalValue) when using nullable(true) is in fact null? I work on a project which has all types as nullable (including number) and it works well as expected.

I did encounter the issue when a value coming from an input was empty string (which is, of course NaN). If it happens that you want certain values such as empty string to be considered null, you can use transform first, something like:

const quantity = number().positive().nullable(true /* or false */).transform(v => v === '' ? null : v)

In which case, if nullable(true), then empty strings would also be valid. Otherwise, empty string would be transformed to null but fail if nullable(false)

Perhaps you can borrow from the.default(...) value when a cast doesn’t work. So .default(undefined) would return the same for empty string and .default(0) would return 0 for an empty string.

Additionally, you can see how this error is nasty, (using yup and formik), which is why I came to post about it.

weird-validation-error

@simoami the way I was dealing with it was:

number().transform(v => v === '' ? void 0 : v)

I think the above makes sense (number.js:19) in that, we wouldn’t always want default to 0 when it’s an empty string. In my use case, an empty string (from input field) meant undefined and not 0

I’m having the same problem with yup.string().nullable(), any other way to fix it?

field: yup.string().when('type', {
      is: type => type === true,
      then: yup
        .string()
        .required(),
      else: yup.string().nullable(true),
    }),

Were you able to fix this? I am also dealing with this issue.

If the schema passes the validation I would expect the same value be also castable via the schema.

This isn’t the case right now.

const age = yup.number().nullable();
if (age.validate(null)) {
  age.cast(null); // quantity must be a number type, but the final value was: NaN (cast from the value NaN).
}