vitest-dev/vitest · error · Error

Unable to parse thresholds from configuration file: ${messag

Error message

Unable to parse thresholds from configuration file: ${message}

What it means

Outer wrapper at coverage.ts:869 — any error while reading thresholds from the config file (the inner check at 252, or a property-access failure on an undefined nested path) is rethrown with the 'Unable to parse thresholds from configuration file:' prefix and the inner message appended.

Source

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

  }
}

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') {
      return mod
    }

    // "export default defineConfig(...)"
    let config = resolveDefineConfig(mod)
    if (config) {
      return config

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Read the inner message after the colon — it identifies the actual problem (most often error 252).
  2. Ensure coverage.thresholds is an object in the config file.
  3. If autoUpdate is on, define thresholds in the file before enabling it.

Example fix

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

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

Strategy: try-catch

Validate before calling

try {
  assertThresholdsShape(config)
} catch (e) {
  throw new Error(`Thresholds parse failed: ${(e as Error).message}`)
}

Type guard

function thresholdsParsed(t: unknown): t is Record<string, number> {
  return t != null && typeof t === 'object' && !Array.isArray(t)
  && Object.values(t).every(v => typeof v === 'number')
}

Try / catch

try { resolveThresholdsFromConfig(cfg) }
catch (e) {
  const msg = (e as Error).message
  if (msg.startsWith('Unable to parse thresholds')) handleConfigError(msg)
  throw e
}

Prevention

When it happens

Trigger: Anything that throws inside the thresholds parse block: thresholds is a non-object, or test/coverage nested paths are missing in the parsed config file.

Common situations: Misconfigured thresholds; autoUpdate running against a config file that doesn't define coverage.thresholds at all.

Related errors


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