jquense/yup · error · TypeError

Exclusive tests must provide a unique `name` identifying the

Error message

Exclusive tests must provide a unique `name` identifying the test

What it means

Exclusive tests (which replace any same-named test rather than running alongside it) must have a `name` so they can be identified and replaced. This TypeError is thrown when opts.exclusive is true but no name was provided.

Source

Thrown at src/schema.ts:794

      opts = { name: args[0], test: args[1] };
    } else {
      opts = { name: args[0], message: args[1], test: args[2] };
    }

    if (opts.message === undefined) opts.message = locale.default;

    if (typeof opts.test !== 'function')
      throw new TypeError('`test` is a required parameters');

    let next = this.clone();
    let validate = createValidation(opts);

    let isExclusive =
      opts.exclusive || (opts.name && next.exclusiveTests[opts.name] === true);

    if (opts.exclusive) {
      if (!opts.name)
        throw new TypeError(
          'Exclusive tests must provide a unique `name` identifying the test',
        );
    }

    if (opts.name) next.exclusiveTests[opts.name] = !!opts.exclusive;

    next.tests = next.tests.filter((fn) => {
      if (fn.OPTIONS!.name === opts.name) {
        if (isExclusive) return false;
        if (fn.OPTIONS!.test === validate.OPTIONS.test) return false;
      }
      return true;
    });

    next.tests.push(validate);

    return next;
  }

View on GitHub (pinned to ff31eee8a2)

Solutions

  1. Add a unique name: .test({ name: 'myTest', exclusive: true, test: fn })
  2. If no overriding is intended, remove exclusive: true
  3. Match the built-in test's name exactly if the goal is to override it

Example fix

// before
yup.number().test({ exclusive: true, test: v => v < 100 });
// after
yup.number().test({ name: 'lessThan100', exclusive: true, test: v => v < 100 });
Defensive patterns

Strategy: validation

Validate before calling

if (opts.exclusive && !opts.name) throw new Error('exclusive tests need a name');
schema.test({ name: 'myTest', exclusive: true, test: fn });

Type guard

function isValidExclusiveTest(o: { exclusive?: boolean; name?: string }): boolean {
  return !o.exclusive || typeof o.name === 'string' && o.name.length > 0;
}

Try / catch

try { schema.test(opts); } catch (e) { if (/Exclusive tests/.test(e.message)) schema.test({ ...opts, name: opts.name ?? 'anonTest' }); else throw e; }

Prevention

When it happens

Trigger: Calling .test({ exclusive: true, test: fn }) or .test(undefined, 'msg', fn, true) without a name; the fourth positional argument sets exclusive but the first (name) is missing.

Common situations: Setting exclusive: true to override a built-in/default test but forgetting the name; copying the positional-args signature and passing true as the 4th argument without a name string.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of jquense/yup@ff31eee8a2 (2026-08-31). Data as JSON: /api/errors/09ea9ec0790f071d. Report an issue: GitHub.