avajs/ava · error · AssertionError
(validateExpectations error for t.throws())
Error message
(validateExpectations error for t.throws())
What it means
When the expectations argument of t.throws() is invalid, AVA's validateExpectations() throws its own descriptive error (e.g. about bad constructor/regex/message shapes); t.throws catches it and re-throws it via fail() so it is recorded as a failed assertion. The bracketed message is a placeholder — the real text comes from validateExpectations.
Source
Thrown at lib/assert.js:417
// Since arrow functions do not support 'arguments', we are using rest
// operator, so we can determine the total number of arguments passed
// to the function.
let [fn, expectations, message] = args;
assertMessage(message, 't.throws()');
if (typeof fn !== 'function') {
throw fail(new AssertionError('`t.throws()` must be called with a function', {
assertion: 't.throws()',
improperUsage: {assertion: 'throws'},
formattedDetails: [formatWithLabel('Called with:', fn)],
}));
}
try {
expectations = validateExpectations('t.throws()', expectations, args.length, experiments);
} catch (error) {
throw fail(error);
}
let retval;
let threw = false;
let actual = null;
try {
retval = fn();
if (isPromise(retval)) {
// Here isPromise() checks if something is "promise like". Cast to an actual promise.
Promise.resolve(retval).catch(noop);
throw fail(new AssertionError(message, {
assertion: 't.throws()',
formattedDetails: [formatWithLabel('Function returned a promise. Use `t.throwsAsync()` instead:', retval)],
}));
}
} catch (error) {
threw = true;
actual = error;View on GitHub (pinned to bbfd946322)
Solutions
- Read the underlying validateExpectations message in the error output for the exact offending expectation.
- Pass a constructor (e.g. TypeError), RegExp, string, or a valid object like {instanceOf, message, name}.
- Use {instanceOf: ErrorClass} instead of passing an Error instance.
Example fix
// before
t.throws(fn, new TypeError('boom'));
// after
t.throws(fn, { instanceOf: TypeError, message: 'boom' }); Defensive patterns
Strategy: validation
Validate before calling
function isValidExpectation(e) {
if (e == null || typeof e === 'function' || typeof e === 'string' || e instanceof RegExp) return true;
if (typeof e !== 'object') return false;
return ['instanceOf','message','name','code','is','truthy'].some(k => k in e);
} Type guard
const validThrowsExpectation = (e) =>
e === undefined || typeof e === 'function' || typeof e === 'string' ||
e instanceof RegExp || (typeof e === 'object' && e !== null &&
!Array.isArray(e)); Try / catch
try {
t.throws(fn, expectations);
} catch (err) {
if (/expectation/i.test(err.message)) {
t.fail('Invalid t.throws() expectations: ' + err.message);
} else { throw err; }
} Prevention
- Pass constructors (Error subclasses), RegExp, or {instanceOf, message} — never Error instances.
- Keep the argument order: fn, expectations, message.
- Re-check expectation shapes after AVA version upgrades.
When it happens
Trigger: t.throws(fn, expectations, ...) where expectations is not undefined/function/regex/string/object of the allowed shape (e.g. passing a number, or {message: 42}), or passing >3 args.
Common situations: Passing an Error instance instead of a constructor; passing a string expectation where a regex is required; upgrading AVA and using a no-longer-supported expectations form.
Related errors
- (validateExpectations error for t.throwsAsync())
- `t.like()` selector must not contain circular references
- `t.throws()` must be called with a function
- `t.throwsAsync()` must be called with a function or promise
- The `any` property of the second argument to `${assertion}`
AI-assisted analysis of avajs/ava@bbfd946322 (2026-09-02).
Data as JSON: /api/errors/21cff671b5945d9f.
Report an issue: GitHub.