oxc-project/oxc · warning
Expect in a promise chain must be awaited or returned
Error message
Expect in a promise chain must be awaited or returned
What it means
Diagnostic from the shared jest/vitest `valid-expect-in-promise` rule (expect_in_unhandled_promise). It fires when an `expect()` call lives inside a `.then()`/`.catch()`/`.finally()` callback of a promise that is neither awaited nor returned from the test. The test function returns before the callback runs, so failures vanish and the test is a false pass.
Source
Thrown at crates/oxc_linter/src/rules/shared/jest_vitest/valid_expect_in_promise.rs:21
AstKind,
ast::{
Argument, CallExpression, Expression, FunctionBody, MemberExpression,
SimpleAssignmentTarget, Statement,
},
};
use oxc_ast_visit::{VisitJs, walk_js};
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{GetSpan, Span};
use oxc_str::CompactStr;
use rustc_hash::{FxHashMap, FxHashSet};
use crate::{
context::LintContext,
utils::{JestGeneralFnKind, PossibleJestNode, get_node_name_vec, parse_general_jest_fn_call},
};
fn expect_in_unhandled_promise(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Expect in a promise chain must be awaited or returned")
.with_help("Either `await` the promise, `return` it, or use `expect().resolves`/`expect().rejects`.")
.with_label(span)
}
fn expect_in_promise_after_return(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Expect in a promise chain is unreachable after a `return` statement")
.with_help("Move the promise before the `return` and ensure it is awaited or returned.")
.with_label(span)
}
pub const DOCUMENTATION: &str = r"### What it does
Ensures that `expect` calls inside promise chains (`.then()`, `.catch()`,
`.finally()`) are properly awaited or returned from the test.
### Why is this bad?
When `expect` is called inside a promise callback that is not awaited orView on GitHub (pinned to e1e7af627c)
Solutions
- Make the test async and `await` the chain: `it('x', async () => { await fetchData().then((d) => expect(d).toBe(1)); });`.
- Or `return` the chain from the test: `return fetchData().then(...)`.
- Or drop the chain: `const d = await fetchData(); expect(d).toBe(1);`.
- For promise assertions use `await expect(p).resolves.toBe(1)` / `.rejects` instead of .then/.catch wrappers.
Example fix
// before
it('loads', () => {
fetchData().then((data) => expect(data.length).toBe(1));
});
// after
it('loads', async () => {
const data = await fetchData();
expect(data.length).toBe(1);
}); Defensive patterns
Strategy: validation
Validate before calling
// detect expect inside then/catch/finally callbacks
const floating = /\.(then|catch|finally)\s*\(\s*\(?[^)]*\)?\s*=>\s*(\{[^}]*|)expect\s*\(/;
if (floating.test(src)) console.warn('expect() inside a promise chain callback — await or return it'); Prevention
- Write new tests as `async/await` only; never `.then()` inside test bodies.
- If you must keep a chain, `return` it from the test so the runner awaits it.
- Enable oxlint's valid-expect-in-promise plus @typescript-eslint no-floating-promises in CI.
When it happens
Trigger: The rule parses general jest function calls (test/it handlers) and inspects promise-chain member expressions; when an expect sits in the callback and the chain is floating, this diagnostic is emitted. Examples: `it('x', () => { fetchData().then((d) => expect(d).toBe(1)); });` or `.catch(() => expect(err).toBeDefined());` without await/return.
Common situations: Legacy promise-chain tests written before async/await, tests where a refactor removed `return` from `return promise.then(...)`, and fire-and-forget `.catch` handlers that swallow assertion errors.
Related errors
- Promises which return async assertions must be awaited.
- Expect in a promise chain is unreachable after a `return` st
- Async assertions must be awaited.
- Matchers must be called to assert.
- Expect has an unknown modifier.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/c28e98dc620bf207.
Report an issue: GitHub.