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
- Add a unique name: .test({ name: 'myTest', exclusive: true, test: fn })
- If no overriding is intended, remove exclusive: true
- 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
- Always name custom tests, even non-exclusive ones
- Match built-in test names exactly when overriding them
- Review the 4-argument positional form; prefer the options object
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
- `test` is a required parameters
- Only valid options for round() are: ${avail.join(', ')}
- You cannot `concat()` schema's of different types: ${this.ty
- The value of ${options.path || 'field'} could not be cast to
- Validation test of type: "${ctx.type}" returned a Promise du
AI-assisted analysis of jquense/yup@ff31eee8a2 (2026-08-31).
Data as JSON: /api/errors/09ea9ec0790f071d.
Report an issue: GitHub.