avajs/ava · error · AssertionError

The assertion message must be a string

Error message

The assertion message must be a string

What it means

AVA assertion messages must be a string or undefined. assertMessage (lib/assert.js:279) runs checkAssertionMessage on the message passed to any assertion and throws a generic Error (produced by fail(result)) when the message is neither undefined nor a string. This guards assertion output formatting: AVA cannot render non-string messages.

Source

Thrown at lib/assert.js:279

	constructor({
		pass = notImplemented,
		pending = notImplemented,
		fail = notImplemented,
		failPending = notImplemented,
		skip = notImplemented,
		compareWithSnapshot = notImplemented,
		experiments = {},
		disableSnapshots = false,
	} = {}) {
		const withSkip = assertionFn => {
			assertionFn.skip = skip;
			return assertionFn;
		};

		const assertMessage = (message, assertion) => {
			const result = checkAssertionMessage(message, assertion);
			if (result !== true) {
				throw fail(result);
			}
		};

		this.pass = withSkip(() => pass());

		this.fail = withSkip(message => {
			assertMessage(message, 't.fail()');

			throw fail(new AssertionError(message ?? 'Test failed via `t.fail()`', {
				assertion: 't.fail()',
			}));
		});

		this.is = withSkip((actual, expected, message) => {
			assertMessage(message, 't.is()');

			if (Object.is(actual, expected)) {
				return pass();

View on GitHub (pinned to bbfd946322)

Solutions

  1. Convert the value to a string before passing it: t.is(actual, expected, String(message)) or template literal `${message}`.
  2. Pass the Error's message property instead of the Error itself: t.fail(err.message).
  3. Omit the argument entirely (or pass undefined) if no message is needed; null must be removed since only undefined/string are accepted.

Example fix

// before
t.fail(new Error('boom'));

// after
t.fail('boom'); // or t.fail(error.message)
Defensive patterns

Strategy: type-guard

Validate before calling

function isAssertionMessage(m) { return m === undefined || typeof m === 'string'; }
if (!isAssertionMessage(message)) throw new TypeError('Assertion message must be a string');

Type guard

const isAssertionMessage = (m) => m === undefined || typeof m === 'string';

Prevention

When it happens

Trigger: Calling any t.* assertion (t.fail(), t.is(), t.deepEqual(), t.true(), t.log-like assertions, etc.) with a message argument that is a number, boolean, object, Error, null, or other non-string, non-undefined value — e.g. t.is(got, want, 42) or t.fail(someError).

Common situations: Passing an Error object as the message out of habit from other frameworks, interpolating to a number, passing null explicitly (null is not undefined), or refactoring where a variable that is sometimes an object is used as the message.

Related errors


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