vitest-dev/vitest · error · TypeError

invalid return value in globalSetup file

Error message

invalid return value in globalSetup file ${globalSetupFile.file}. Must return a function

What it means

When loading globalSetup files, Vitest calls each setup function and, if the file does not export its own teardown, treats the setup return value as the teardown. If that return value is non-null but not a function, Vitest throws a TypeError because it cannot call it later as a teardown.

Solutions

  1. Return either nothing (undefined/null) or a function from globalSetup setup.
  2. If you need richer teardown, export an explicit teardown export from the globalSetup file instead.
  3. Ensure async setup resolves to a function (or undefined), not an object.

Example fix

// before
export function setup() {
  return { cleanup() {} } // object, not a function
}
// after
export function setup() {
  return function cleanup() {}
}
// or export teardown explicitly
export function teardown() {}
Defensive patterns

Strategy: validation

Validate before calling

// Validate globalSetup return shape during development.
function validateGlobalSetupReturn(ret: unknown) {
  if (ret != null && typeof ret !== 'function') {
  throw new TypeError('globalSetup setup must return undefined or a function, got ' + typeof ret)
  }
}

Type guard

const isTeardownOrAbsent = (ret: unknown): ret is undefined | (() => unknown | Promise<unknown>) =>
  ret == null || typeof ret === 'function'

Prevention

When it happens

Trigger: A globalSetup file's setup() returns a truthy non-function (e.g. an object, a Promise resolving to an object, a number) and the file does not export an explicit teardown.

Common situations: Refactoring a globalSetup to return a cleanup object instead of a function, forgetting that async setup returning a non-function value triggers this, or copy-paste from a setup that returned a closure.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/55197931c5037f75. Report an issue: GitHub.

Appendix: source

Thrown at packages/vitest/src/node/project.ts:241

  /** @internal */
  async _initializeGlobalSetup() {
    if (this._globalSetups) {
      return
    }

    this._globalSetups = await loadGlobalSetupFiles(
      this.runner,
      this.config.globalSetup,
    )

    for (const globalSetupFile of this._globalSetups) {
      const teardown = await globalSetupFile.setup?.(this)
      if (teardown == null || !!globalSetupFile.teardown) {
        continue
      }
      if (typeof teardown !== 'function') {
        throw new TypeError(
          `invalid return value in globalSetup file ${globalSetupFile.file}. Must return a function`,
        )
      }
      globalSetupFile.teardown = teardown
    }
  }

  onTestsRerun(cb: OnTestsRerunHandler): void {
    this.vitest.onTestsRerun(cb)
  }

  /** @internal */
  async _teardownGlobalSetup(): Promise<void> {
    if (!this._globalSetups) {
      return
    }
    for (const globalSetupFile of [...this._globalSetups].reverse()) {
      await globalSetupFile.teardown?.()

View on GitHub (pinned to 1fa9837ec2)