{"id":"07f8a6bc2b7462bd","repo":"vitest-dev/vitest","slug":"calling-the-suite-function-inside-test-function-is","errorCode":null,"errorMessage":"Calling the suite function inside test function is not allowed. It can be only called at the top level or inside another suite function.","messagePattern":"Calling the suite function inside test function is not allowed\\. It can be only called at the top level or inside another suite function\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/runtime/runner/suite.ts","lineNumber":593,"sourceCode":"        .map(r => (r.status === 'rejected' ? r.reason : undefined))\n        .filter(Boolean)\n      if (errors.length) {\n        throw errors\n      }\n    }\n    return fnResult\n  }) as T\n}\n\nfunction createSuite() {\n  function suiteFn(\n    this: Record<string, boolean | undefined>,\n    name: string | Function,\n    factoryOrOptions?: SuiteFactory | SuiteOptions,\n    optionsOrFactory?: number | SuiteFactory,\n  ) {\n    if (getCurrentTest()) {\n      throw new Error(\n        'Calling the suite function inside test function is not allowed. It can be only called at the top level or inside another suite function.',\n      )\n    }\n\n    const currentSuite: SuiteCollector | undefined = collectorContext.currentSuite || defaultSuite\n\n    let { options, handler: factory } = parseArguments(\n      factoryOrOptions,\n      optionsOrFactory,\n    ) as { options: SuiteOptions; handler: SuiteFactory | undefined }\n\n    const { meta: parentMeta, ...parentOptions } = currentSuite?.options || {}\n    // inherit options from current suite\n    options = {\n      ...parentOptions,\n      ...options,\n    }\n","sourceCodeStart":575,"sourceCodeEnd":611,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/runtime/runner/suite.ts#L575-L611","documentation":"The `suite`/`describe` factory function checks `getCurrentTest()` at call time (suite.ts:592-596). Defining a suite inside a running test is disallowed because suite collection occurs before test execution — a suite declared mid-test could never be collected. Suites may only be declared at the top level or nested inside other suites.","triggerScenarios":"Writing `test('x', () => { describe('inner', () => { ... }) })`; calling `suite(...)` from within a test body or a function invoked during a test; dynamic suite creation at runtime.","commonSituations":"Porting from frameworks that permit runtime suite definition; helper functions that wrap `describe`; conditionally building suites inside tests.","solutions":["Move `describe`/`suite` declarations to the top level or inside another `describe`.","Use `test.each`/`describe.each` for parameterized grouping instead of runtime suite creation.","If logic must be conditional, use `describe.skipIf`/`test.runIf` at the suite level."],"exampleFix":"// before\ntest('setup', () => {\n  describe('group', () => { // throws\n    test('a', () => {})\n  })\n})\n// after\ndescribe('group', () => {\n  test('setup', () => {})\n  test('a', () => {})\n})","handlingStrategy":"validation","validationCode":"// Structural: ensure describe()/suite() are not lexically nested inside test() bodies.\n// ESLint: ban CallExpression callees 'describe'/'suite' inside test callbacks.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare suites at top level or inside other suites only.","Use describe.each / describe.skipIf for conditional grouping.","Refactor runtime suite builders into static declarations."],"tags":["suite-definition","nesting","collection","lifecycle"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}