avajs/ava · error · TypeError
Expected an implementation.
Error message
Expected an implementation.
What it means
AVA's t.try() requires an implementation function as its argument (optionally with a title and args). When t.try() is called without a function (e.g. undefined, null, or only a non-function value), the constructor throws this TypeError because there is nothing to execute for the attempt.
Source
Thrown at lib/test.js:105
this.timeout.clear = () => {
test.clearTimeout();
};
this.teardown = callback => {
test.addTeardown(callback);
};
this.try = async (...attemptArgs) => {
if (test.isHook) {
const error = new Error('`t.try()` can only be used in tests');
test.saveFirstError(error);
throw error;
}
const {args, implementation, title} = parseTestArgs(attemptArgs);
if (typeof implementation !== 'function') {
throw new TypeError('Expected an implementation.');
}
let attemptTitle;
if (!title.isSet || title.isEmpty) {
attemptTitle = `${test.title} ─ attempt ${test.attemptCount + 1}`;
} else if (title.isValid) {
attemptTitle = `${test.title} ─ ${title.value}`;
} else {
throw new TypeError('`t.try()` titles must be strings');
}
if (!test.registerUniqueTitle(attemptTitle)) {
throw new Error(`Duplicate test title: ${attemptTitle}`);
}
let committed = false;
let discarded = false;
View on GitHub (pinned to bbfd946322)
Solutions
- Pass an actual function to t.try(): t.try(tt => { ... }) or t.try('title', tt => { ... }).
- Verify the implementation identifier is defined and imported correctly (check for undefined variables/imports).
- If passing arguments, use the signature t.try(title, implementation, ...args) with implementation as the second argument.
Example fix
// before
const attempt = t.try('checks value', someValue);
// after
const attempt = t.try('checks value', (tt, value) => {
tt.is(value, 42);
}, someValue); Defensive patterns
Strategy: validation
Validate before calling
if (typeof impl !== 'function') throw new TypeError('t.try() requires an implementation function');
const attempt = t.try('title', impl, ...args); Type guard
const isFunction = (v) => typeof v === 'function';
Try / catch
try {
attempt = t.try(...attemptArgs);
} catch (err) {
if (err instanceof TypeError && err.message === 'Expected an implementation.') {
throw new Error('Bug in test: t.try() called without a function');
}
throw err;
} Prevention
- Always pass the implementation as the last non-args argument to t.try()
- Enable TypeScript or linter rules that catch non-function arguments
- Check imports after refactors so the callback variable is never undefined
- Remember the signature: t.try(title?, implementation, ...args)
When it happens
Trigger: t.try() called with no arguments; t.try('title') with a title but no implementation; t.try(cb) where cb is undefined due to a bad import or hoisting issue; passing args-only without a function (e.g. t.try('title', arg1) missing the function).
Common situations: Refactoring renamed the callback so the variable is undefined; copying the t.try(title, impl, ...args) signature but forgetting impl; passing a non-function like a promise or an async result instead of the test function.
Related errors
- `t.try()` titles must be strings
- Expected a function
- Expected an implementation. Use `test.todo()` for tests with
- Test & hook titles must be strings
- Tests must have a title
AI-assisted analysis of avajs/ava@bbfd946322 (2026-09-02).
Data as JSON: /api/errors/f4f90ed1cb5aa418.
Report an issue: GitHub.