{"record":{"id":"f57d458d6aa74c9e","repo":"vitest-dev/vitest","slug":"expected-config-test-coverage-thresholds-to-be-an","errorCode":null,"errorMessage":"Expected config.test.coverage.thresholds to be an object","messagePattern":"Expected config\\.test\\.coverage\\.thresholds to be an object","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/coverage.ts","lineNumber":862,"sourceCode":"      'functions' in thresholds && typeof thresholds.functions === 'number'\n        ? thresholds.functions\n        : undefined,\n    statements:\n      'statements' in thresholds && typeof thresholds.statements === 'number'\n        ? thresholds.statements\n        : undefined,\n  }\n}\n\nfunction assertConfigurationModule(config: unknown): asserts config is {\n  test: {\n    coverage: { thresholds: NonNullable<CoverageOptions['thresholds']> }\n  }\n} {\n  try {\n    // @ts-expect-error -- Intentional unsafe null pointer check as wrapped in try-catch\n    if (typeof config.test.coverage.thresholds !== 'object') {\n      throw new TypeError(\n        'Expected config.test.coverage.thresholds to be an object',\n      )\n    }\n  }\n  catch (error) {\n    const message = error instanceof Error ? error.message : String(error)\n    throw new Error(\n      `Unable to parse thresholds from configuration file: ${message}`,\n    )\n  }\n}\n\nfunction resolveConfig(configModule: any) {\n  const mod = configModule.exports.default\n\n  try {\n    // Check for \"export default { test: {...} }\"\n    if (mod.$type === 'object') {","sourceCodeStart":844,"sourceCodeEnd":880,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/node/coverage.ts#L844-L880","documentation":"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.","triggerScenarios":"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'.","commonSituations":"Misformed config; thresholds at the wrong nesting level; copy-paste from docs using shorthand; thresholds partially deleted.","solutions":["Set thresholds as an object: coverage: { thresholds: { lines: 80 } }.","Ensure test.coverage exists in the config file.","Remove thresholds entirely if not needed."],"exampleFix":"// before\nexport default defineConfig({\n  test: { coverage: { thresholds: 80 } }\n})\n\n// after\nexport default defineConfig({\n  test: { coverage: { thresholds: { lines: 80, functions: 80 } } }\n})","handlingStrategy":"validation","validationCode":"function thresholdsIsObject(cfg) {\n  return cfg?.test?.coverage?.thresholds != null\n    && typeof cfg.test.coverage.thresholds === 'object'\n    && !Array.isArray(cfg.test.coverage.thresholds)\n}\n// load config module, assert before enabling autoUpdate","typeGuard":"function isThresholdsObject(v): v is Record<string, number> {\n  return v != null && typeof v === 'object' && !Array.isArray(v)\n}","tryCatchPattern":null,"preventionTips":["Always nest thresholds as an object: coverage.thresholds = { lines: 80 }.","Type-check the config file with `vitest.config` types before enabling autoUpdate.","Avoid shorthand numbers for thresholds."],"tags":["coverage","thresholds","config-validation"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}