avajs/ava · error · AssertionError

(validateExpectations error for t.throwsAsync())

Error message

(validateExpectations error for t.throwsAsync())

What it means

In t.throwsAsync(), invalid expectations cause validateExpectations('t.throwsAsync()', ...) to throw a descriptive usage error, which is caught and re-thrown through fail() so AVA records it as a failed assertion. Before rethrowing, AVA awaits the thrower (swallowing its rejection) to avoid leaving an unhandled promise rejection. The bracketed message is a placeholder for the underlying validateExpectations text.

Source

Thrown at lib/assert.js:456

			if (!threw) {
				throw fail(new AssertionError(message, {
					assertion: 't.throws()',
					formattedDetails: [formatWithLabel('Function returned:', retval)],
				}));
			}

			try {
				assertExpectations({
					assertion: 't.throws()',
					actual,
					expectations,
					message,
					prefix: 'Function threw',
				});
				pass();
				return actual;
			} catch (error) {
				throw fail(error);
			}
		});

		this.throwsAsync = withSkip(async (...args) => {
			let [thrower, expectations, message] = args;

			try {
				assertMessage(message, 't.throwsAsync()');
			} catch (error) {
				try {
					await thrower;
				} catch {}

				throw error;
			}

			if (typeof thrower !== 'function' && !isPromise(thrower)) {
				throw fail(new AssertionError('`t.throwsAsync()` must be called with a function or promise', {

View on GitHub (pinned to bbfd946322)

Solutions

  1. Read the underlying validateExpectations message for the precise offending expectation.
  2. Use a constructor, RegExp, string, or valid object ({instanceOf, message, name, code? per docs}).
  3. Replace Error instances with {instanceOf: ErrorClass} expectations.

Example fix

// before
await t.throwsAsync(promise, new RangeError('out of range'));
// after
await t.throwsAsync(promise, { instanceOf: RangeError, message: 'out of range' });
Defensive patterns

Strategy: validation

Validate before calling

function isValidExpectation(e) {
  return e === undefined || typeof e === 'function' || typeof e === 'string' ||
    e instanceof RegExp || (typeof e === 'object' && e !== null && !Array.isArray(e));
}
if (!isValidExpectation(expectations)) throw new TypeError('bad t.throwsAsync expectations');

Type guard

const validThrowsAsyncExpectation = (e) => isValidExpectation(e);

Try / catch

try {
  await t.throwsAsync(thrower, expectations);
} catch (err) {
  if (/expectation/i.test(err.message)) {
    t.fail('Invalid t.throwsAsync() expectations: ' + err.message);
  } else { throw err; }
}

Prevention

When it happens

Trigger: await t.throwsAsync(promiseOrFn, expectations, ...) with a malformed expectations argument: wrong type (number, boolean, Error instance), an object with unsupported keys, or too many arguments.

Common situations: Passing an instantiated Error instead of a constructor; copy-pasting expectations between t.throws/t.throwsAsync incorrectly; AVA version changes to accepted expectation shapes.

Related errors


AI-assisted analysis of avajs/ava@bbfd946322 (2026-09-02). Data as JSON: /api/errors/4dc3830f1958dec7. Report an issue: GitHub.