{"record":{"id":"f0171fa0ab2bdf58","repo":"avajs/ava","slug":"the-snapshot-assertion-message-must-be-a-non-empty","errorCode":null,"errorMessage":"The snapshot assertion message must be a non-empty string","messagePattern":"The snapshot assertion message must be a non-empty string","errorType":"validation","errorClass":"AssertionError","httpStatus":null,"severity":"warning","filePath":"lib/assert.js","lineNumber":644,"sourceCode":"\t\t\t\t\tassertion: 't.notThrowsAsync()',\n\t\t\t\t\tformattedDetails: [formatWithLabel('Function did not return a promise. Use `t.notThrows()` instead:', retval)],\n\t\t\t\t}));\n\t\t\t}\n\n\t\t\treturn handlePromise(retval, true);\n\t\t});\n\n\t\tthis.snapshot = withSkip((expected, message) => {\n\t\t\tif (disableSnapshots) {\n\t\t\t\tthrow fail(new AssertionError('`t.snapshot()` can only be used in tests', {\n\t\t\t\t\tassertion: 't.snapshot()',\n\t\t\t\t}));\n\t\t\t}\n\n\t\t\tassertMessage(message, 't.snapshot()');\n\n\t\t\tif (message === '') {\n\t\t\t\tthrow fail(new AssertionError('The snapshot assertion message must be a non-empty string', {\n\t\t\t\t\tassertion: 't.snapshot()',\n\t\t\t\t\tformattedDetails: [formatWithLabel('Called with:', message)],\n\t\t\t\t}));\n\t\t\t}\n\n\t\t\tlet result;\n\t\t\ttry {\n\t\t\t\tresult = compareWithSnapshot({expected, message});\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof SnapshotError)) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\n\t\t\t\tconst improperUsage = {assertion: 'snapshot', name: error.name, snapPath: error.snapPath};\n\t\t\t\tif (error instanceof VersionMismatchError) {\n\t\t\t\t\timproperUsage.snapVersion = error.snapVersion;\n\t\t\t\t\timproperUsage.expectedVersion = error.expectedVersion;\n\t\t\t\t}","sourceCodeStart":626,"sourceCodeEnd":662,"githubUrl":"https://github.com/avajs/ava/blob/bbfd946322fdeca2b547a691d947fb4e18c0c67f/lib/assert.js#L626-L662","documentation":"t.snapshot(expected, message) accepts an optional message label for the snapshot; AVA requires it to be a non-empty string when provided, because empty labels make snapshots ambiguous and unmaintainable. Passing an empty string explicitly triggers this AssertionError with the offending value in the details.","triggerScenarios":"Calling t.snapshot(value, ''); computing the message dynamically from a variable that ends up as an empty string; template literals interpolating empty values (t.snapshot(v, `prefix ${x}`) where x is '').","commonSituations":"Auto-generated test code inserting empty labels; i18n/l10n lookups returning '' for missing keys used as snapshot messages; copy-pasted assertions where someone cleared the message instead of removing the argument.","solutions":["Omit the second argument entirely instead of passing ''","Provide a descriptive non-empty string message","If the message is dynamic, validate/fallback before asserting: msg || undefined"],"exampleFix":"// before\nt.snapshot(user, '');\n// after\nt.snapshot(user, 'authenticated user');\n// or with a dynamic label:\nt.snapshot(user, label || undefined);","handlingStrategy":"validation","validationCode":"function snapshotLabeled(t, value, message) {\n  if (message === '') message = undefined; // empty string is invalid; omit instead\n  t.snapshot(value, message);\n}","typeGuard":"const isValidSnapshotMessage = (m) =>\n  m === undefined || m === null || (typeof m === 'string' && m.length > 0);","tryCatchPattern":"try {\n  t.snapshot(value, label);\n} catch (e) {\n  if (/non-empty string/.test(e.message)) {\n    t.snapshot(value); // retry without a label\n  } else {\n    throw e;\n  }\n}","preventionTips":["Omit the message argument rather than passing ''","Validate dynamic/i18n labels resolve to non-empty strings before asserting","Lint test code against empty-string literal arguments to snapshot"],"tags":["ava","snapshot","assertion-message","validation"],"backgroundTag":"assertion-message-empty-string","analyzedSha":"bbfd946322fdeca2b547a691d947fb4e18c0c67f","analyzedAt":"2026-09-02T01:24:43.834Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}