{"id":"d73076eb59571ae9","repo":"vitest-dev/vitest","slug":"error-instanceof-error-error-message-string","errorCode":null,"errorMessage":"${error instanceof Error ? error.message : String(error)}","messagePattern":"\\$\\{error instanceof Error \\? error\\.message : String\\(error\\)\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/coverage.ts","lineNumber":900,"sourceCode":"    }\n\n    // \"export default defineConfig(...)\"\n    let config = resolveDefineConfig(mod)\n    if (config) {\n      return config\n    }\n\n    // \"export default mergeConfig(..., defineConfig(...))\"\n    if (mod.$type === 'function-call' && mod.$callee === 'mergeConfig') {\n      config = resolveMergeConfig(mod)\n      if (config) {\n        return config\n      }\n    }\n  }\n  catch (error) {\n    // Reduce magicast's verbose errors to readable ones\n    throw new Error(error instanceof Error ? error.message : String(error))\n  }\n\n  throw new Error(\n    'Failed to update coverage thresholds. Configuration file is too complex.',\n  )\n}\n\nfunction resolveDefineConfig(mod: any) {\n  if (mod.$type === 'function-call' && mod.$callee === 'defineConfig') {\n    // \"export default defineConfig({ test: {...} })\"\n    if (mod.$args[0].$type === 'object') {\n      return mod.$args[0]\n    }\n\n    if (mod.$args[0].$type === 'arrow-function-expression') {\n      if (mod.$args[0].$body.$type === 'object') {\n        // \"export default defineConfig(() => ({ test: {...} }))\"\n        return mod.$args[0].$body","sourceCodeStart":882,"sourceCodeEnd":918,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/node/coverage.ts#L882-L918","documentation":"resolveConfig (coverage.ts:900) catches magicast errors while statically analyzing the config AST and rethrows just the message. This is the generic fallback for any unparseable shape while walking defineConfig/mergeConfig/inline-object forms during the autoUpdate flow.","triggerScenarios":"A config file whose AST magicast cannot statically resolve — computed property keys, dynamic imports, runtime-spread conditionals, calls to unknown helper functions.","commonSituations":"Highly dynamic config files; configs that wrap defineConfig in custom helpers; configs that build the test object conditionally at runtime.","solutions":["Simplify the config so thresholds sit inside a plain export default defineConfig({ test: { coverage: { thresholds: {...} } } }).","Move dynamic logic out of the config file (env-based branching, etc.).","Disable autoUpdate and update thresholds manually if the config must stay dynamic."],"exampleFix":"// before\nexport default defineConfig(() => buildConfig(env))\n\n// after\nexport default defineConfig({ test: { coverage: { thresholds: { lines: 80 } } } })","handlingStrategy":"fallback","validationCode":"try {\n  await reporter.updateThresholds(...)\n} catch (e) {\n  console.warn('Static config rewrite failed; falling back to manual thresholds')\n}","typeGuard":"function isStaticallyParseable(ast: any): boolean {\n  return ast?.exports?.default?.$type === 'object'\n    || ast?.exports?.default?.$callee === 'defineConfig'\n    || ast?.exports?.default?.$callee === 'mergeConfig'\n}","tryCatchPattern":"try { resolveConfig(mod) }\ncatch (e) { throw new Error(`Config too dynamic to rewrite thresholds: ${(e as Error).message}`) }","preventionTips":["Keep the config file static and standard (export default defineConfig({...})).","Move dynamic/conditional logic out of the config file.","Disable autoUpdate if the config must stay dynamic."],"tags":["coverage","config","thresholds","autoupdate","magicast"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}