avajs/ava · error · TypeError
Tests must have a title
Error message
Tests must have a title
What it means
Unlike hooks, tests cannot fall back to an auto-generated title. When the declared title is empty (empty string or no title given) and metadata.type is 'test', AVA throws this TypeError. Hooks tolerate empty titles (they get '<type> hook' fallbacks) because they are identifiable by type, but plain tests must have a human-readable title.
Source
Thrown at lib/runner.js:141
this.emit('stateChange', {
type: 'declared-test',
title: title.value,
knownFailing: false,
todo: true,
});
} else {
if (typeof implementation !== 'function') {
throw new TypeError('Expected an implementation. Use `test.todo()` for tests without an implementation.');
}
if (title.isSet && !title.isValid) {
throw new TypeError('Test & hook titles must be strings');
}
let fallbackTitle = title.value;
if (title.isEmpty) {
if (metadata.type === 'test') {
throw new TypeError('Tests must have a title');
} else if (metadata.always) {
fallbackTitle = `${metadata.type}.always hook`;
} else {
fallbackTitle = `${metadata.type} hook`;
}
}
if (metadata.type === 'test' && !this.registerUniqueTitle(title.value)) {
throw new Error(`Duplicate test title: ${title.value}`);
}
const task = {
title: title.value ?? fallbackTitle,
implementation,
args,
metadata: {...metadata},
};
View on GitHub (pinned to bbfd946322)
Solutions
- Provide a descriptive title string for every test
- If the title is dynamic, guard against empty values with a fallback: title || 'default title'
- If the call was meant to be a hook, use beforeEach/afterEach etc., which tolerate empty titles
- If the test is a placeholder, use test.todo('title')
Example fix
// before
test('', t => { ... });
// after
test('handles empty input', t => { ... }); Defensive patterns
Strategy: validation
Validate before calling
if (metadata.type === 'test' && (title === undefined || title === '')) {
throw new TypeError('Tests must have a non-empty title');
}
test(title, fn); Type guard
function hasNonEmptyTitle(title) {
return typeof title === 'string' && title.trim().length > 0;
} Try / catch
try {
test(title, fn);
} catch (err) {
if (err.message === 'Tests must have a title') {
test('untitled test', fn);
} else {
throw err;
}
} Prevention
- Always give tests explicit descriptive titles
- Add a default/fallback when titles are computed: title || 'fallback title'
- Validate interpolated dynamic titles are non-empty before use
- Do not copy hook-style (titleless) declarations to plain tests
When it happens
Trigger: test('', t => {}) with an empty-string title; test(t => {}) where parseTestArgs treats the function-only call as having no title; dynamic title variables that evaluate to '' at runtime.
Common situations: Building titles by string concatenation where both parts are empty; a refactor that removed the title argument; copying a hook declaration pattern (which allows empty titles) to a test; generated tests where an interpolation produced ''.
Related errors
- Expected an implementation. Use `test.todo()` for tests with
- Test & hook titles must be strings
- Duplicate test title: ${title.value}
- Expected an implementation.
- `t.try()` titles must be strings
AI-assisted analysis of avajs/ava@bbfd946322 (2026-09-02).
Data as JSON: /api/errors/4a4d0416f1918f43.
Report an issue: GitHub.