jestjs/jest · error · ErrorWithStack
A "describe" callback must not return a value.
Error message
A "describe" callback must not return a value.
What it means
After invoking the describe callback, _dispatchDescribe also rejects any non-undefined, non-Promise return value (index.ts:83-87). The callback is meant only to register tests and hooks as a side effect; returning a value is almost always a typo (an accidental arrow-function shorthand return) that would silently lose the intended side effect.
Solutions
- Wrap the callback body in curly braces so calls are statements, not the return value (describe('x', () => { test(...); }).
- Audit the describe callback for any return/implicit-return of an expression and convert to void or statement form.
- If you genuinely need the value, move it into a hook or a variable assignment.
Example fix
// before
describe('math', () =>
test('adds', () => expect(1 + 1).toBe(2)));
// after
describe('math', () => {
test('adds', () => expect(1 + 1).toBe(2));
}); Defensive patterns
Strategy: validation
Validate before calling
// Reject describe callbacks whose return type is non-void statically (TS):
// type SyncDescribeFn = () => void;
function registerDescribe(name: string, fn: () => void) {
describe(name, fn);
}
registerDescribe('x', () => { test('y', () => {}); }); // OK
// registerDescribe('x', () => test('y', () => {})); // TS error: not assignable to () => void Type guard
function returnsVoid(fn: (...args: any[]) => unknown): boolean {
// static check via TS is preferred; runtime heuristic for audits:
return fn.constructor.name !== 'AsyncFunction';
} Prevention
- Type describe callbacks explicitly as () => void so implicit returns become TS errors.
- Always wrap describe callback bodies in curly braces.
- Run tsc --noImplicitReturns or enable the corresponding lint to catch implicit returns.
When it happens
Trigger: Writing describe('x', () => test('y', () => {})) where the arrow implicitly returns the result of test(); any describe callback using the concise arrow body form that evaluates an expression; describe.each with a callback that returns a value.
Common situations: Accidentally dropping the braces on an arrow function inside describe so it returns test(...) instead of calling it as a statement; refactoring a callback from braces to expression form; copy-paste from a function that returns a value.
Related errors
- Returning a Promise from "describe" is not supported. Tests…
- describe does not expect any arguments
- Invalid second argument
- Jest: `failing` tests are only supported in `jest-circus`.
- Missing second argument. It must be a callback function.
AI-assisted analysis of jestjs/jest@8e6d128e4a (2026-08-10).
Data as JSON: /api/errors/60caa7fcd816f695.
Report an issue: GitHub.
Appendix: source
Thrown at packages/jest-circus/src/index.ts:84
asyncError.message = (error as Error).message;
throw asyncError;
}
dispatchSync({
asyncError,
blockName,
mode,
name: 'start_describe_definition',
});
const describeReturn = blockFn();
if (isPromise(describeReturn)) {
throw new ErrorWithStack(
'Returning a Promise from "describe" is not supported. Tests must be defined synchronously.',
describeFn,
);
} else if (describeReturn !== undefined) {
throw new ErrorWithStack(
'A "describe" callback must not return a value.',
describeFn,
);
}
dispatchSync({blockName, mode, name: 'finish_describe_definition'});
};
const _addHook = (
fn: Circus.HookFn,
hookType: Circus.HookType,
hookFn: THook,
timeout?: number,
) => {
const asyncError = new ErrorWithStack(undefined, hookFn);
if (typeof fn !== 'function') {
asyncError.message =View on GitHub (pinned to 8e6d128e4a)