avajs/ava · error · AssertionError
`t.throws()` must be called with a function
Error message
`t.throws()` must be called with a function
What it means
AVA throws this fixed usage error when t.throws() is invoked with a first argument that is not a function. t.throws() synchronously invokes its argument to observe a throw, so anything other than a callable is improper usage; the error is flagged with improperUsage so AVA can point at a mistake in the test rather than a failure of the code under test.
Source
Thrown at lib/assert.js:407
const actualDescriptor = result.actual ?? concordance.describe(comparable, concordanceOptions);
const expectedDescriptor = result.expected ?? concordance.describe(selector, concordanceOptions);
throw fail(new AssertionError(message, {
assertion: 't.like()',
formattedDetails: [formatDescriptorDiff(actualDescriptor, expectedDescriptor)],
}));
});
this.throws = withSkip((...args) => {
// 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)) {View on GitHub (pinned to bbfd946322)
Solutions
- Wrap the call in a function: t.throws(() => risky()).
- If the code is asynchronous, switch to t.throwsAsync(() => riskyAsync()).
- Check that the variable holding the function is actually defined and is a function.
Example fix
// before
t.throws(readConfig('missing.json'));
// after
t.throws(() => readConfig('missing.json')); Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof fn !== 'function') throw new TypeError('t.throws() expects a function; got ' + typeof fn); Type guard
const isCallable = (v) => typeof v === 'function';
if (!isCallable(fn)) { /* fix before asserting */ } Try / catch
try {
t.throws(fn, expectations);
} catch (err) {
if (/must be called with a function/.test(err.message)) {
t.fail('Wrap the call in a thunk: t.throws(() => ...)');
} else { throw err; }
} Prevention
- Always pass an arrow-function wrapper: t.throws(() => code()).
- Never pass a promise or awaited result to t.throws — use t.throwsAsync for async code.
- Check for undefined function variables before the assertion.
When it happens
Trigger: t.throws(undefined), t.throws(await asyncFn()), t.throws(promise) — passing the result of an async call, a promise, or forgetting to pass a thunk, e.g. t.throws(fs.readFileSync('nope')) instead of () => fs.readFileSync('nope').
Common situations: Calling the function eagerly instead of wrapping it in an arrow function; migrating from t.throwsAsync and passing a promise; typo'd variable that is undefined at call time.
Related errors
- `t.throwsAsync()` must be called with a function or promise
- `t.like()` selector must not contain circular references
- (validateExpectations error for t.throws())
- (validateExpectations error for t.throwsAsync())
- `t.notThrows()` must be called with a function
AI-assisted analysis of avajs/ava@bbfd946322 (2026-09-02).
Data as JSON: /api/errors/e3929dad7fe4c93f.
Report an issue: GitHub.