oxc-project/oxc · warning
Async assertions must be awaited.
Error message
Async assertions must be awaited.
What it means
Diagnostic from the shared jest/vitest `valid-expect` rule (Message::AsyncMustBeAwaited). It fires when an assertion that resolves asynchronously — one using the `resolves`/`rejects` modifiers or a matcher listed in `asyncMatchers` config (default `toResolve`, `toReject`) — is left floating: neither awaited nor returned from the test. The process can exit before the assertion runs, producing false-green tests.
Source
Thrown at crates/oxc_linter/src/rules/shared/jest_vitest/valid_expect.rs:23
use oxc_semantic::ScopeId;
use oxc_span::{GetSpan, Span};
use rustc_hash::FxHashSet;
use schemars::JsonSchema;
use crate::{
AstNode,
context::LintContext,
utils::{
ExpectError, PossibleJestNode, collect_possible_jest_call_node, parse_expect_jest_fn_call,
},
};
fn valid_expect_diagnostic<S: Into<Cow<'static, str>>>(
x1: S,
x2: &'static str,
span3: Span,
) -> OxcDiagnostic {
OxcDiagnostic::warn(x1).with_help(x2).with_label(span3)
}
pub const DOCUMENTATION: &str = r"### What it does
Checks that `expect()` is called correctly.
### Why is this bad?
`expect()` is a function that is used to assert values in tests.
It should be called with a single argument, which is the value to be tested.
If you call `expect()` with no arguments, or with more than one argument, it will not work as expected.
### Examples
Examples of **incorrect** code for this rule:
```javascript
expect();
expect('something');View on GitHub (pinned to e1e7af627c)
Solutions
- Add `await` in front of the assertion (the rule ships an autofix that also inserts `async` on the enclosing function when needed): `await expect(p).resolves.toBe(1);`.
- Alternatively `return` the assertion from the test function — accepted unless `alwaysAwait` is enabled.
- Enable `alwaysAwait: true` in the rule config to enforce awaiting everywhere, preventing return-based flakes.
- Run `oxlint --fix` to apply the built-in await/async fix across the file.
Example fix
// before
it('resolves', () => {
expect(Promise.resolve(1)).resolves.toBe(1);
});
// after
it('resolves', async () => {
await expect(Promise.resolve(1)).resolves.toBe(1);
}); Defensive patterns
Strategy: validation
Validate before calling
// fail CI when an async assertion is not awaited
// rg -n "^\s*expect\(.*\)\.(resolves|rejects)\." --type ts src/
const { execSync } = require('child_process');
try {
execSync("rg '^\\s*expect\\(.*\\)\\.(resolves|rejects)\\.' src/ --type ts", { stdio: 'pipe' });
console.error('floating async assertions found (missing await/return)');
process.exitCode = 1;
} catch { /* rg exit 1 = no matches, good */ } Prevention
- Enable `alwaysAwait` in valid-expect config so even `return expect(...)` must be awaited.
- Default to `async () => { await expect(p).resolves... }` whenever you type `resolves`/`rejects`/`toResolve`/`toReject`.
- Run tests with vitest/jest `--detectOpenHandles`-style strictness; floating assertions often surface as premature process exit.
When it happens
Trigger: The rule computes `should_be_awaited` when any modifier other than `not` is present or the matcher name is in `asyncMatchers`; if the parent is not an acceptable return/await node (and `alwaysAwait: true` also rejects bare `return`), the diagnostic fires. Examples: `expect(Promise.resolve(1)).resolves.toBe(1);` as a statement, or `it('x', () => { expect(p).toResolve(); })` without await/return.
Common situations: Migrating callback-style tests to async, vitest extension matchers (`toResolve`/`toReject` from @vitest/eslint-plugin or jest-extended), and teams enabling `alwaysAwait` in config so even `return expect(...)...` must become `await`.
Related errors
- Promises which return async assertions must be awaited.
- Matchers must be called to assert.
- Expect has an unknown modifier.
- Expect takes at most {} argument{}
- Expect requires at least {} argument{}
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/e42222f773490116.
Report an issue: GitHub.