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

  1. Provide a descriptive title string for every test
  2. If the title is dynamic, guard against empty values with a fallback: title || 'default title'
  3. If the call was meant to be a hook, use beforeEach/afterEach etc., which tolerate empty titles
  4. 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

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


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