oxc-project/oxc · error
No async describe callback
Error message
No async describe callback
What it means
Diagnostic from the oxlint `jest/valid-describe-callback` rule (source: crates/oxc_linter/src/rules/shared/jest_vitest/valid_describe_callback.rs:18). This variant ('No async describe callback') fires when the describe callback is declared `async`. Describe callbacks only register tests; awaiting inside them skips registration depending on timing, so jest forbids it. The `allow_async_describe_callback` option in `ValidDescribeCallbackOptions` (Jest default: false) can relax this.
Source
Thrown at crates/oxc_linter/src/rules/shared/jest_vitest/valid_describe_callback.rs:18
use oxc_ast::{
AstKind,
ast::{Argument, Expression, FunctionBody, Statement},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{GetSpan, Span};
use crate::{
context::LintContext,
utils::{JestFnKind, JestGeneralFnKind, PossibleJestNode, parse_general_jest_fn_call},
};
fn valid_describe_callback_diagnostic(
x1: &'static str,
x2: &'static str,
span3: Span,
) -> OxcDiagnostic {
OxcDiagnostic::warn(x1).with_help(x2).with_label(span3)
}
#[derive(Clone, Copy)]
pub struct ValidDescribeCallbackOptions {
allow_async_describe_callback: bool,
allow_describe_options_argument: bool,
}
impl ValidDescribeCallbackOptions {
pub const JEST: Self =
Self { allow_async_describe_callback: false, allow_describe_options_argument: false };
pub const VITEST: Self =
Self { allow_async_describe_callback: true, allow_describe_options_argument: true };
}
pub fn run<'a>(
possible_jest_node: &PossibleJestNode<'a, '_>,View on GitHub (pinned to e1e7af627c)
Solutions
- Remove `async` from the describe callback and keep only synchronous registration: `describe('feature', () => { test(...) })`.
- If the async work must happen before tests, do it inside `beforeAll(async () => {...})` - hooks may be async.
- Use top-level await in an ESM test file when the data is available statically.
- As a last resort enable the option: `"jest/valid-describe-callback": ["error", { "allowAsyncDescribeCallback": true }]` in `.oxlintrc.json`.
Example fix
// before
describe('config', async () => {
const cfg = await loadConfig();
test('has port', () => expect(cfg.port).toBeDefined());
});
// after
describe('config', () => {
let cfg;
beforeAll(async () => {
cfg = await loadConfig();
});
test('has port', () => expect(cfg.port).toBeDefined());
}); Defensive patterns
Strategy: validation
Validate before calling
// rg -n "describe\([^)]*async\s*\(\)" tests/ -t ts -t js
Prevention
- Keep describe callbacks synchronous; async work goes in beforeAll/afterAll or top-level await
- When generating suites from async data, load in beforeAll, not in the describe callback
When it happens
Trigger: `describe('feature', async () => { ... })` - an async function expression/arrow as the describe callback, with the rule option `allow_async_describe_callback` at its default `false` (the JEST preset constant in the source).
Common situations: Copy-pasting a test callback into a describe; dynamic test generation that fetches data before declaring tests (the correct pattern is hooks or top-level await in ESM); refactors that made everything async.
Related errors
- Async assertions must be awaited.
- Promises which return async assertions must be awaited.
- Enforces a maximum depth to nested describe calls.
- Describe block title is used multiple times in the same desc
- Require test cases and hooks to be inside a `describe` block
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/d62185794b726c93.
Report an issue: GitHub.