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

  1. Omit the second argument entirely instead of passing ''
  2. Provide a descriptive non-empty string message
  3. 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

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


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