{"record":{"id":"bed49be9b718e560","repo":"avajs/ava","slug":"duplicate-test-title-attempttitle","errorCode":null,"errorMessage":"Duplicate test title: ${attemptTitle}","messagePattern":"Duplicate test title: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/test.js","lineNumber":118,"sourceCode":"\t\t\t}\n\n\t\t\tconst {args, implementation, title} = parseTestArgs(attemptArgs);\n\n\t\t\tif (typeof implementation !== 'function') {\n\t\t\t\tthrow new TypeError('Expected an implementation.');\n\t\t\t}\n\n\t\t\tlet attemptTitle;\n\t\t\tif (!title.isSet || title.isEmpty) {\n\t\t\t\tattemptTitle = `${test.title} ─ attempt ${test.attemptCount + 1}`;\n\t\t\t} else if (title.isValid) {\n\t\t\t\tattemptTitle = `${test.title} ─ ${title.value}`;\n\t\t\t} else {\n\t\t\t\tthrow new TypeError('`t.try()` titles must be strings');\n\t\t\t}\n\n\t\t\tif (!test.registerUniqueTitle(attemptTitle)) {\n\t\t\t\tthrow new Error(`Duplicate test title: ${attemptTitle}`);\n\t\t\t}\n\n\t\t\tlet committed = false;\n\t\t\tlet discarded = false;\n\n\t\t\tconst {assertCount, deferredSnapshotRecordings, errors, logs, passed, snapshotCount, startingSnapshotCount} = await test.runAttempt(attemptTitle, t => implementation(t, ...args));\n\n\t\t\treturn {\n\t\t\t\terrors,\n\t\t\t\tlogs: [...logs], // Don't allow modification of logs.\n\t\t\t\tpassed,\n\t\t\t\ttitle: attemptTitle,\n\t\t\t\tcommit({retainLogs = true} = {}) {\n\t\t\t\t\tif (committed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (discarded) {","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/avajs/ava/blob/bbfd946322fdeca2b547a691d947fb4e18c0c67f/lib/test.js#L100-L136","documentation":"Each title generated for a t.try() attempt must be unique within the test. AVA registers every attempt title (auto-generated 'attempt N' or user-provided) via registerUniqueTitle; when the title was already registered, this Error is thrown to prevent ambiguous test output and snapshot bookkeeping.","triggerScenarios":"Calling t.try twice with the same explicit title inside one test; a loop that creates t.try attempts with identical constant titles; an auto-generated title colliding because the attempt count tracking was bypassed.","commonSituations":"Loops like for (const item of items) { t.try('works', impl) } producing repeated titles; duplicating a t.try line when copy-pasting tests; generating titles from data that contains duplicates.","solutions":["Make titles unique by interpolating the loop variable or an index: t.try(`works: ${item.id}`, impl).","Omit the title so AVA appends a unique 'attempt N' suffix automatically.","Deduplicate or suffix titles from dynamic data before passing them to t.try()."],"exampleFix":"// before\nfor (const user of users) {\n  t.try('validates user', impl);\n}\n\n// after\nusers.forEach((user, i) => {\n  t.try(`validates user ${user.id ?? i}`, impl);\n});","handlingStrategy":"validation","validationCode":"const seen = new Set();\nfunction uniqueTitle(base) {\n  let title = base, i = 1;\n  while (seen.has(title)) title = `${base} (${i++})`;\n  seen.add(title);\n  return title;\n}\nconst attempt = t.try(uniqueTitle('validates user'), impl);","typeGuard":"const isFreshTitle = (title, registered) => !registered.has(title);","tryCatchPattern":"try {\n  const attempt = t.try(title, impl);\n} catch (err) {\n  if (/^Duplicate test title: /.test(err.message)) {\n    throw new Error(`Fix your test: t.try title \"${title}\" used twice`);\n  }\n  throw err;\n}","preventionTips":["Interpolate loop variables into t.try() titles","Omit the title to let AVA auto-generate a unique one","Never hardcode the same title in loops or copy-pasted blocks"],"tags":["ava","t-try","duplicate-title","naming"],"backgroundTag":"duplicate-test-title","analyzedSha":"bbfd946322fdeca2b547a691d947fb4e18c0c67f","analyzedAt":"2026-09-02T01:24:43.834Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}