vitest-dev/vitest · error · TypeError

Expected config.test.coverage.thresholds to be an object

Error message

Expected config.test.coverage.thresholds to be an object

What it means

While parsing the user's config file to auto-update thresholds, Vitest asserts config.test.coverage.thresholds is an object. If that path is missing or non-object (set to a number, string, or undefined), it throws TypeError. The throw is wrapped by the surrounding try/catch (error 249) into a more readable message.

Solutions

  1. Set thresholds as an object: coverage: { thresholds: { lines: 80 } }.
  2. Ensure test.coverage exists in the config file.
  3. Remove thresholds entirely if not needed.

Example fix

// before
export default defineConfig({
  test: { coverage: { thresholds: 80 } }
})

// after
export default defineConfig({
  test: { coverage: { thresholds: { lines: 80, functions: 80 } } }
})
Defensive patterns

Strategy: validation

Validate before calling

function thresholdsIsObject(cfg) {
  return cfg?.test?.coverage?.thresholds != null
    && typeof cfg.test.coverage.thresholds === 'object'
    && !Array.isArray(cfg.test.coverage.thresholds)
}
// load config module, assert before enabling autoUpdate

Type guard

function isThresholdsObject(v): v is Record<string, number> {
  return v != null && typeof v === 'object' && !Array.isArray(v)
}

Prevention

When it happens

Trigger: autoUpdate reads a config file where coverage.thresholds is a non-object (e.g. thresholds: 80 or thresholds: 'lines'), or where test/coverage is missing, so typeof config.test.coverage.thresholds !== 'object'.

Common situations: Misformed config; thresholds at the wrong nesting level; copy-paste from docs using shorthand; thresholds partially deleted.

Related errors


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

Appendix: source

Thrown at packages/vitest/src/node/coverage.ts:862

      'functions' in thresholds && typeof thresholds.functions === 'number'
        ? thresholds.functions
        : undefined,
    statements:
      'statements' in thresholds && typeof thresholds.statements === 'number'
        ? thresholds.statements
        : undefined,
  }
}

function assertConfigurationModule(config: unknown): asserts config is {
  test: {
    coverage: { thresholds: NonNullable<CoverageOptions['thresholds']> }
  }
} {
  try {
    // @ts-expect-error -- Intentional unsafe null pointer check as wrapped in try-catch
    if (typeof config.test.coverage.thresholds !== 'object') {
      throw new TypeError(
        'Expected config.test.coverage.thresholds to be an object',
      )
    }
  }
  catch (error) {
    const message = error instanceof Error ? error.message : String(error)
    throw new Error(
      `Unable to parse thresholds from configuration file: ${message}`,
    )
  }
}

function resolveConfig(configModule: any) {
  const mod = configModule.exports.default

  try {
    // Check for "export default { test: {...} }"
    if (mod.$type === 'object') {

View on GitHub (pinned to 1fa9837ec2)