jaredpalmer/formik · warning

Warning: An unhandled error was caught during validation in

Error message

Warning: An unhandled error was caught during validation in <Formik validate />

What it means

Formik's `validate` function (or `validateYupSchema` path when using plain validate) returned a rejected Promise or threw a non-validation exception. Formik intentionally does not swallow these: it logs a dev-only warning and re-rejects so the error surfaces, because an exception inside `validate` is a bug in user validation code, not a validation result.

Source

Thrown at packages/formik/src/Formik.tsx:211

    // force rerender
    if (prev !== stateRef.current) setIteration(x => x + 1);
  }, []);

  const runValidateHandler = React.useCallback(
    (values: Values, field?: string): Promise<FormikErrors<Values>> => {
      return new Promise((resolve, reject) => {
        const maybePromisedErrors = (props.validate as any)(values, field);
        if (maybePromisedErrors == null) {
          // use loose null check here on purpose
          resolve(emptyErrors);
        } else if (isPromise(maybePromisedErrors)) {
          (maybePromisedErrors as Promise<any>).then(
            errors => {
              resolve(errors || emptyErrors);
            },
            actualException => {
              if (process.env.NODE_ENV !== 'production') {
                console.warn(
                  `Warning: An unhandled error was caught during validation in <Formik validate />`,
                  actualException
                );
              }

              reject(actualException);
            }
          );
        } else {
          resolve(maybePromisedErrors);
        }
      });
    },
    [props.validate]
  );

  /**
   * Run validation against a Yup schema and optionally run a function if successful

View on GitHub (pinned to 91475adbf3)

Solutions

  1. Inspect the second console.warn argument (the actualException) — it contains the real stack and message; fix that underlying throw in your validate function.
  2. Guard nested access: use optional chaining (`values.user?.email`) or lodash `get` inside validate.
  3. Ensure async validate always resolves to an errors object (`return {}` instead of throwing) and wrap any remote calls in try/catch that resolve to a form-level error.
  4. If the exception comes from Yup inside validate, use `validationSchema` instead so Formik maps ValidationError to form errors properly.

Example fix

// before
validate: values => {
  const errors = {};
  if (!values.user.email) errors.email = 'Required'; // throws if user undefined
  return errors;
}
// after
validate: values => {
  const errors = {};
  if (!values.user?.email) errors.email = 'Required';
  return errors;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before wiring validate, smoke-test it against initial values
import { get } from 'lodash';
const errors = safeValidate(validateFn, initialValues);
console.log(errors); // inspect for thrown exceptions vs returned errors

Type guard

const isSafeValidate = (fn: (v: any) => any) =>
  typeof fn === 'function';

// wrap to guarantee resolution to an errors object
const safeValidate = (fn: FormikConfig<V>['validate'], values: V) => {
  try { return fn(values) ?? {}; } catch (e) { return { _: 'Validation crashed' }; }
};

Try / catch

validate: async values => {
  try {
    return await myValidate(values);
  } catch (e) {
    return { form: 'Could not validate, please retry.' };
  }
}

Prevention

When it happens

Trigger: A `validate` or `validateYupSchema` prop that throws/rejects for reasons other than returning errors — e.g. accessing a property of undefined values (`values.user.email` when `user` is undefined), calling an API that rejects inside validate, or returning a Promise that rejects instead of resolving to an errors object.

Common situations: Deeply nested initial values not pre-populated (undefined path access), async validation calling a backend that 500s, a Yup schema reused with `.validate()` that throws a non-ValidationError, or a refactor that made validate async without awaiting internals.

Related errors


AI-assisted analysis of jaredpalmer/formik@91475adbf3 (2026-08-27). Data as JSON: /api/errors/0d7de98d0b357b9c. Report an issue: GitHub.