oxc-project/oxc · warning · OxcDiagnostic

Duplicate {hook_name:?} in describe block.

Error message

Duplicate {hook_name:?} in describe block.

What it means

Diagnostic from oxlint rule `jest/no-duplicate-hooks` (shared with vitest) in crates/oxc_linter/src/rules/shared/jest_vitest/no_duplicate_hooks.rs:16. Inside one describe block each lifecycle hook type (beforeAll, beforeEach, afterAll, afterEach) may appear only once; the rule reports the second and later occurrence of the same hook_name. Duplicate hooks all execute in order, which is confusing and error-prone.

Source

Thrown at crates/oxc_linter/src/rules/shared/jest_vitest/no_duplicate_hooks.rs:16

use oxc_ast::AstKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_semantic::NodeId;
use oxc_span::Span;
use rustc_hash::FxHashMap;

use crate::{
    context::LintContext,
    utils::{
        JestFnKind, JestGeneralFnKind, ParsedJestFnCallNew, PossibleJestNode,
        collect_possible_jest_call_node, parse_jest_fn_call,
    },
};

fn no_duplicate_hooks_diagnostic(hook_name: &str, span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("Duplicate {hook_name:?} in describe block."))
        .with_help("Describe blocks can only have one of each hook. Consider consolidating the duplicate hooks into a single call.")
        .with_label(span)
}

pub const DOCUMENTATION: &str = r"### What it does

Disallows duplicate hooks in describe blocks.

### Why is this bad?

Having duplicate hooks in a describe block can lead to confusion and unexpected behavior.
When multiple hooks of the same type exist, they all execute in order, which can make it
difficult to understand the test setup flow and may result in redundant or conflicting
operations. This makes tests harder to maintain and debug.

### Examples

Examples of **incorrect** code for this rule:

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Merge the duplicate hooks into a single call, preserving the original execution order of their bodies
  2. If the hooks belong to different concerns, move one to a nested describe so each scope keeps one hook of each type
  3. Delete the stale hook when its logic was already inlined into the surviving one

Example fix

// before
describe('cart', () => {
  beforeEach(() => { seedCart(); });
  beforeEach(() => { login(); });
});

// after
describe('cart', () => {
  beforeEach(() => { seedCart(); login(); });
});
Defensive patterns

Strategy: validation

Validate before calling

npx oxlint -c .oxlintrc.json tests/ # jest/no-duplicate-hooks reports the second same-type hook per describe

Prevention

When it happens

Trigger: Two or more calls to the same hook kind inside the same describe scope, e.g. two beforeEach blocks; the rule parses jest fn calls via parse_jest_fn_call and keeps an FxHashMap of seen hooks per describe node, reporting the duplicate's span.

Common situations: Copy-pasting setup into a second beforeEach instead of merging; merging branches that each added their own beforeAll; refactoring a describe and accidentally leaving the old hook; partial cleanup after moving hooks around.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/25b5034a054e6563. Report an issue: GitHub.