avajs/ava · warning · AssertionError
The snapshot assertion message must be a non-empty string
Error message
The snapshot assertion message must be a non-empty string
What it means
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.
Source
Thrown at lib/assert.js:644
assertion: 't.notThrowsAsync()',
formattedDetails: [formatWithLabel('Function did not return a promise. Use `t.notThrows()` instead:', retval)],
}));
}
return handlePromise(retval, true);
});
this.snapshot = withSkip((expected, message) => {
if (disableSnapshots) {
throw fail(new AssertionError('`t.snapshot()` can only be used in tests', {
assertion: 't.snapshot()',
}));
}
assertMessage(message, 't.snapshot()');
if (message === '') {
throw fail(new AssertionError('The snapshot assertion message must be a non-empty string', {
assertion: 't.snapshot()',
formattedDetails: [formatWithLabel('Called with:', message)],
}));
}
let result;
try {
result = compareWithSnapshot({expected, message});
} catch (error) {
if (!(error instanceof SnapshotError)) {
throw error;
}
const improperUsage = {assertion: 'snapshot', name: error.name, snapPath: error.snapPath};
if (error instanceof VersionMismatchError) {
improperUsage.snapVersion = error.snapVersion;
improperUsage.expectedVersion = error.expectedVersion;
}View on GitHub (pinned to bbfd946322)
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
Example fix
// before t.snapshot(user, ''); // after t.snapshot(user, 'authenticated user'); // or with a dynamic label: t.snapshot(user, label || undefined);
Defensive patterns
Strategy: validation
Validate before calling
function snapshotLabeled(t, value, message) {
if (message === '') message = undefined; // empty string is invalid; omit instead
t.snapshot(value, message);
} Type guard
const isValidSnapshotMessage = (m) => m === undefined || m === null || (typeof m === 'string' && m.length > 0);
Try / catch
try {
t.snapshot(value, label);
} catch (e) {
if (/non-empty string/.test(e.message)) {
t.snapshot(value); // retry without a label
} else {
throw e;
}
} Prevention
- 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
When it happens
Trigger: 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 '').
Common situations: 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.
Related errors
- Cannot record snapshot ${index} for ${JSON.stringify(belongs
- `t.snapshot()` can only be used in tests
- Could not compare snapshot
- Did not match snapshot
- No snapshot available — new snapshots are not created in CI
AI-assisted analysis of avajs/ava@bbfd946322 (2026-09-02).
Data as JSON: /api/errors/f0171fa0ab2bdf58.
Report an issue: GitHub.