avajs/ava · error · AssertionError

The second argument to `${assertion}` contains unexpected pr

Error message

The second argument to `${assertion}` contains unexpected properties

What it means

Thrown by validateExpectations in lib/assert.js:150 when the expectation object passed as the second argument to a throws assertion contains a key that is not one of the allowed properties: instanceOf, is, message, name, code, any. This catches typos like `mesage` or `instenceOf` that would otherwise be silently ignored and make the assertion weaker than intended.

Source

Thrown at lib/assert.js:150

			throw new AssertionError(`The \`any\` property of the second argument to \`${assertion}\` must be a boolean`, {
				assertion,
				formattedDetails: [formatWithLabel('Called with:', expectations)],
			});
		}

		for (const key of Object.keys(expectations)) {
			switch (key) {
				case 'instanceOf':
				case 'is':
				case 'message':
				case 'name':
				case 'code':
				case 'any': {
					continue;
				}

				default: {
					throw new AssertionError(`The second argument to \`${assertion}\` contains unexpected properties`, {
						assertion,
						formattedDetails: [formatWithLabel('Called with:', expectations)],
					});
				}
			}
		}
	}

	return expectations;
}

// Note: this function *must* throw exceptions, since it can be used
// as part of a pending assertion for promises.
function assertExpectations({actual, expectations, message, prefix, assertion, assertionStack}) {
	const allowThrowAnything = Object.hasOwn(expectations, 'any') && expectations.any;
	if (!isNativeError(actual) && !allowThrowAnything) {
		throw new AssertionError(message, {
			assertion,

View on GitHub (pinned to bbfd946322)

Solutions

  1. Remove the unexpected key, or fix its spelling to one of: instanceOf, is, message, name, code, any.
  2. If you intended to assert extra properties on the error, assert them separately after capturing the thrown value (e.g. `const err = t.throws(...)` then check `err.code`).
  3. Check the library docs / types for the exact expectation object shape for the version you are using.

Example fix

// before
t.throws(fn, { mesage: 'boom' });

// after
t.throws(fn, { message: 'boom' });
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = new Set(['instanceOf', 'is', 'message', 'name', 'code', 'any']);
function assertKnownKeys(expectations) {
  for (const key of Object.keys(expectations ?? {})) {
    if (!ALLOWED.has(key)) throw new TypeError(`Unknown expectation key: ${key}`);
  }
}

Type guard

function isExpectationObject(e) {
  const allowed = ['instanceOf', 'is', 'message', 'name', 'code', 'any'];
  return e != null && typeof e === 'object' && !Array.isArray(e) &&
    Object.keys(e).every(k => allowed.includes(k));
}

Try / catch

try {
  t.throws(fn, expectations);
} catch (error) {
  if (error.name === 'AssertionError' && /unexpected properties/.test(error.message)) {
    console.warn('Bad expectation keys:', Object.keys(expectations));
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling t.throws(fn, {mesage: 'x'}), t.throws(fn, {type: 'Error'}), t.throwsAsync(p, {code: 'ERR', foo: 1}) — any expectation key outside the allowed set hits the switch's default branch.

Common situations: Typos in expectation keys (most common: `mesage`, `instanceOf` vs `instanceof`); reusing options from other assertion libraries (e.g. Chai's `.throw(Error, /msg/, props)` style); spreading extra runtime data into the expectations object; renaming library APIs across versions.

Related errors


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