vitest-dev/vitest · error · Error

The vcsProvider module '${vcsProvider}' doesn't have a defau

Error message

The vcsProvider module '${vcsProvider}' doesn't have a default export with `findChangedFiles` method.

What it means

Thrown by `loadVcsProvider` (vcs.ts:24) when a custom `vcsProvider` module path is configured but the imported module's `default` export is missing, not an object, or lacks a `findChangedFiles` function. Vitest requires `{ default: { findChangedFiles(options) } }` so it can wrap and call the provider; any other shape is rejected.

Source

Thrown at packages/vitest/src/node/vcs/vcs.ts:24

  root: string
  changedSince?: string | boolean
}

export interface VCSProvider {
  // eslint-disable-next-line ts/method-signature-style
  findChangedFiles(options: VCSProviderOptions): Promise<string[]>
}

export async function loadVCSProvider(runner: ModuleRunner, vcsProvider: string | VCSProvider | undefined): Promise<VCSProvider> {
  if (typeof vcsProvider === 'object' && vcsProvider != null) {
    return wrapVCSProvider(vcsProvider)
  }
  if (!vcsProvider || vcsProvider === 'git') {
    return new GitVCSProvider()
  }
  const module = await runner.import(vcsProvider) as { default: VCSProvider }
  if (!module.default || typeof module.default !== 'object' || typeof module.default.findChangedFiles !== 'function') {
    throw new Error(`The vcsProvider module '${vcsProvider}' doesn't have a default export with \`findChangedFiles\` method.`)
  }
  return wrapVCSProvider(module.default)
}

function wrapVCSProvider(provider: VCSProvider): VCSProvider {
  return {
    async findChangedFiles(options) {
      const changedFiles = await provider.findChangedFiles(options)
      return changedFiles.map(file => resolve(options.root, file))
    },
  }
}

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Ensure the module has `export default { findChangedFiles(options) { /* ... */ } }`.
  2. Verify the configured `vcsProvider` path resolves to the provider file.
  3. Confirm `findChangedFiles` returns an array of absolute/relative changed file paths as expected by `wrapVCSProvider`.

Example fix

// before
export const provider = { async changedFiles(opt) { /* ... */ } }
// after
export default {
  async findChangedFiles(options) { /* return string[] of changed files */ }
}
Defensive patterns

Strategy: validation

Validate before calling

const mod = await import(vcsProviderPath)
const def = mod.default
if (!def || typeof def !== 'object' || typeof def.findChangedFiles !== 'function') {
  throw new Error(`vcsProvider ${vcsProviderPath} must default-export { findChangedFiles }`)
}

Type guard

const isVCSProvider = (m: unknown): m is { default: { findChangedFiles(o: any): Promise<string[]> } } =>
  !!m && typeof m === 'object' && 'default' in m &&
  typeof (m as any).default?.findChangedFiles === 'function'

Prevention

When it happens

Trigger: Setting `test.vcsProvider: './my-vcs.ts'` where the module has only named exports, exports a default that isn't an object, or exports an object without a `findChangedFiles` method; pointing at a module that is a utility file rather than a VCS provider.

Common situations: Authoring a custom VCS provider and forgetting the `default` export; renaming `findChangedFiles` to something else; pointing at the wrong file.

Related errors


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