vitest-dev/vitest · error · Error

invalid export in globalSetup file ${file}: ${exp} must be a

Error message

invalid export in globalSetup file ${file}: ${exp} must be a function

What it means

loadGlobalSetupFile (globalSetup.ts:28) imports the module and, for each of default/setup/teardown, requires that a defined export be a function. If any of those names is exported as something else (object, string, array), vitest rejects it rather than calling a non-function.

Source

Thrown at packages/vitest/src/node/globalSetup.ts:28

export async function loadGlobalSetupFiles(
  runner: ModuleRunner,
  globalSetup: string | string[],
): Promise<GlobalSetupFile[]> {
  const globalSetupFiles = toArray(globalSetup)
  return Promise.all(
    globalSetupFiles.map(file => loadGlobalSetupFile(file, runner)),
  )
}

async function loadGlobalSetupFile(
  file: string,
  runner: ModuleRunner,
): Promise<GlobalSetupFile> {
  const m = await runner.import(file)
  for (const exp of ['default', 'setup', 'teardown']) {
    if (m[exp] != null && typeof m[exp] !== 'function') {
      throw new Error(
        `invalid export in globalSetup file ${file}: ${exp} must be a function`,
      )
    }
  }
  if (m.default) {
    return {
      file,
      setup: m.default,
    }
  }
  else if (m.setup || m.teardown) {
    return {
      file,
      setup: m.setup,
      teardown: m.teardown,
    }
  }
  else {

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Make each of default/setup/teardown a function (or remove it).
  2. Rename unrelated exports so they don't collide with the reserved names.
  3. Use the default-export form: export default function setup(provide) { ... }.

Example fix

// before
export const setup = { hooks: [...] }

// after
export function setup(provide) { /* ... */ }
Defensive patterns

Strategy: type-guard

Validate before calling

for (const k of ['default', 'setup', 'teardown']) {
  if (mod[k] != null && typeof mod[k] !== 'function') {
    throw new TypeError(`globalSetup export '${k}' must be a function`)
  }
}

Type guard

function isFunctionExport(mod: any, key: string): boolean {
  return mod[key] == null || typeof mod[key] === 'function'
}

Prevention

When it happens

Trigger: A globalSetup file that exports default, setup, or teardown as a non-function value — e.g. a config object, an array of hooks, or a constant.

Common situations: Accidentally exporting a config/helper object under one of the reserved names; refactoring a setup file and leaving a stale export.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/2d50f13e90d7f6ee.json. Report an issue: GitHub.