12
votes

I'm using Yup to validate my form. In one of my form, I want to validate that one <input type="file" /> has a file.

I've tested this (and it's not working):

Yup.object().shape({
  file: Yup.object().shape({
    name: Yup.string().required()
}).required('File required')

I've the following error message in the console:

file must be a object type, but the final value was: null (cast from the value {}). If "null" is intended as an empty value be sure to mark the schema as .nullable()

Any idea?

3
For peeps in the future, this issue here explains it: github.com/jaredpalmer/formik/issues/926flash

3 Answers

5
votes

I know this is an old question, but I came across this same issue and tracked down what was happening.

When the validator runs, it's testing that the field type matches first. In this case, it checks to see if it's an object. Since it's not and the field is not marked as nullable, it fails the validation with a type error. Yup never gets to the point of running required() as it bails early.

So how do we adjust the message displayed when the type doesn't match and you don't want to use the nullable() method? I looked at the source and discovered that the message is generated here. So it's part of the locale object. Thus, we can resolve it like this.

import * as Yup from 'yup';
import { setLocale } from 'yup';

setLocale({
  mixed: {
    notType: '${path} is required',
  }
})

Yup.object().shape({
  file: Yup.object().shape({
  name: Yup.string().required()
}).label('File')

Now when the type is incorrect, your new message will display. The label() method allows you to set a nice display name for the field as the message will be used in any invalid type situations in the validators.

Another alternative is to write a custom validator specifically for this field, but that seems like overkill in this scenario.

3
votes

Here is how I did it

import { object, string, mixed } from "yup"

const schema = object().shape({
  attachment: mixed().test("fileSize", "The file is too large", (value) => {
    if (!value.length) return true // attachment is optional
    return value[0].size <= 2000000
  }),
})
0
votes

I solved it like this:

const schema = Yup.object().shape({
    file: Yup.mixed().required('File is required'),
})

It throws an error if you attempt to submit the form without a file, and the error goes away when you have a file.