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 the Promise check, jest-circus also rejects any non-undefined return value from a describe callback (packages/jest-circus/src/index.ts:83). describe must only register tests/hooks via side effects; returning a value is treated as a mistake because that value is silently discarded by the runner and usually indicates an unintended arrow-function return.
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 f49721c78e)
Solutions
- Convert the describe callback to a block body that does not return: `describe('x', () => { configure(); })`.
- If the value is meant to be shared across tests, assign it to a variable declared in the describe scope or move the computation into beforeAll.
- Add an eslint rule or code review check that flags returned values inside describe.
Example fix
// before
describe('config', () => loadConfig());
// after
describe('config', () => {
loadConfig();
}); Defensive patterns
Strategy: validation
Validate before calling
// Ensure the describe factory returns nothing.
function syncDescribe(name: string, fn: () => void): void {
const result = fn();
if (result !== undefined) throw new Error('describe callback returned a value');
} Type guard
type DescribeFn = () => void; // enforce void return via TS const isVoidReturning = (fn: () => unknown): fn is () => void => true;
Prevention
- Type describe callbacks as `() => void` so TS flags returned values.
- Avoid expression-bodied arrows inside describe.
- Code-review for accidental returns after refactors.
When it happens
Trigger: `describe('x', () => configure())` where configure() returns a non-Promise value; `describe('x', () => { return config; })`; an arrow callback whose last expression evaluates to an object/array/number.
Common situations: Refactoring a function into a describe body and forgetting to convert an expression-bodied arrow to a statement block. Returning a helper's result that the author assumed would be used.
Related errors
- Returning a Promise from "describe" is not supported. Tests
- Todo must be called with only a description.
- Missing second argument. It must be a callback function.
- Invalid second argument, ${specDefinitions}. It must be a ca
- describe does not expect any arguments
AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03).
Data as JSON: /data/errors/60caa7fcd816f695.json.
Report an issue: GitHub.