{"record":{"id":"4a4d0416f1918f43","repo":"avajs/ava","slug":"tests-must-have-a-title","errorCode":null,"errorMessage":"Tests must have a title","messagePattern":"Tests must have a title","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/runner.js","lineNumber":141,"sourceCode":"\t\t\t\tthis.emit('stateChange', {\n\t\t\t\t\ttype: 'declared-test',\n\t\t\t\t\ttitle: title.value,\n\t\t\t\t\tknownFailing: false,\n\t\t\t\t\ttodo: true,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tif (typeof implementation !== 'function') {\n\t\t\t\t\tthrow new TypeError('Expected an implementation. Use `test.todo()` for tests without an implementation.');\n\t\t\t\t}\n\n\t\t\t\tif (title.isSet && !title.isValid) {\n\t\t\t\t\tthrow new TypeError('Test & hook titles must be strings');\n\t\t\t\t}\n\n\t\t\t\tlet fallbackTitle = title.value;\n\t\t\t\tif (title.isEmpty) {\n\t\t\t\t\tif (metadata.type === 'test') {\n\t\t\t\t\t\tthrow new TypeError('Tests must have a title');\n\t\t\t\t\t} else if (metadata.always) {\n\t\t\t\t\t\tfallbackTitle = `${metadata.type}.always hook`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfallbackTitle = `${metadata.type} hook`;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (metadata.type === 'test' && !this.registerUniqueTitle(title.value)) {\n\t\t\t\t\tthrow new Error(`Duplicate test title: ${title.value}`);\n\t\t\t\t}\n\n\t\t\t\tconst task = {\n\t\t\t\t\ttitle: title.value ?? fallbackTitle,\n\t\t\t\t\timplementation,\n\t\t\t\t\targs,\n\t\t\t\t\tmetadata: {...metadata},\n\t\t\t\t};\n","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/avajs/ava/blob/bbfd946322fdeca2b547a691d947fb4e18c0c67f/lib/runner.js#L123-L159","documentation":"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.","triggerScenarios":"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.","commonSituations":"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 ''.","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')"],"exampleFix":"// before\ntest('', t => { ... });\n\n// after\ntest('handles empty input', t => { ... });","handlingStrategy":"validation","validationCode":"if (metadata.type === 'test' && (title === undefined || title === '')) {\n\tthrow new TypeError('Tests must have a non-empty title');\n}\ntest(title, fn);","typeGuard":"function hasNonEmptyTitle(title) {\n\treturn typeof title === 'string' && title.trim().length > 0;\n}","tryCatchPattern":"try {\n\ttest(title, fn);\n} catch (err) {\n\tif (err.message === 'Tests must have a title') {\n\t\ttest('untitled test', fn);\n\t} else {\n\t\tthrow err;\n\t}\n}","preventionTips":["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"],"tags":["ava","missing-title","typeerror","api-misuse"],"backgroundTag":"missing-required-title","analyzedSha":"bbfd946322fdeca2b547a691d947fb4e18c0c67f","analyzedAt":"2026-09-02T01:24:43.834Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}