{"id":"648acc1807530722","repo":"vitest-dev/vitest","slug":"environment-ctx-environment-name-is-not-a-val","errorCode":null,"errorMessage":"Environment \"${ctx.environment.name}\" is not a valid environment. Path \"${packageId}\" doesn't support vm environment because it doesn't provide \"setupVM\" method.","messagePattern":"Environment \"(.+?)\" is not a valid environment\\. Path \"(.+?)\" doesn't support vm environment because it doesn't provide \"setupVM\" method\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/runtime/workers/vm.ts","lineNumber":52,"sourceCode":"  const { environment } = await loadEnvironment(ctx.environment.name, ctx.config.root, rpc, traces, true)\n  state.environment = environment\n\n  // let the server transform this file's import graph while this worker is\n  // busy importing the environment package (jsdom takes ~0.5s per worker) —\n  // the server is otherwise idle during that window on a cold start. The\n  // transforms also land in the `fetchWarmModules` snapshot, so the worker's\n  // own fetches short-circuit to disk reads. Failures are ignored: the\n  // worker's own fetch reports them with the proper import context.\n  rpc.prewarmModuleGraph(\n    environment.viteEnvironment || environment.name,\n    ctx.files.map(file => file.filepath),\n  ).catch(() => {})\n\n  if (!environment.setupVM) {\n    const envName = ctx.environment.name\n    const packageId\n      = envName[0] === '.' ? envName : `vitest-environment-${envName}`\n    throw new TypeError(\n      `Environment \"${ctx.environment.name}\" is not a valid environment. `\n      + `Path \"${packageId}\" doesn't support vm environment because it doesn't provide \"setupVM\" method.`,\n    )\n  }\n\n  const vm = await traces.$(\n    'vitest.runtime.environment.setup',\n    {\n      attributes: {\n        'vitest.environment': environment.name,\n        'vitest.environment.vite_environment': environment.viteEnvironment || environment.name,\n      },\n    },\n    () => environment.setupVM!(ctx.environment.options || ctx.config.environmentOptions || {}),\n  )\n\n  state.durations.environment = performance.now() - beforeEnvironmentTime\n","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/runtime/workers/vm.ts#L34-L70","documentation":"In the VM pool (runVmTests, vm.ts:48-56) Vitest requires the environment package to implement a setupVM method that returns a VM context, because the whole pool runs tests inside node:vm. If the resolved vitest-environment-<name> package only exports setup (not setupVM), this TypeError is thrown with the resolved packageId.","triggerScenarios":"Using pool: 'vmThreads' or 'vmForks' with an environment whose package lacks setupVM — e.g. a custom environment that only implements setup, or a built-in/environment combo that does not support the VM isolation model. Reached when environment.setupVM is falsy after loadEnvironment resolves.","commonSituations":"Switching from threads to vmThreads without verifying the environment supports VM mode; writing a custom environment and forgetting setupVM; using an older environment package version that predates setupVM support.","solutions":["Use pool: 'threads' or 'forks' if your environment only provides setup.","Add a setupVM(options) method to your custom environment that returns an object with getVmContext().","Upgrade the environment package (e.g. @vitest/browser or jsdom env) to a version that supports VM mode."],"exampleFix":"// before: custom env with only setup\nexport default {\n  name: 'myenv',\n  setup(global, options) { /* ... */ },\n}\n\n// after: add setupVM for vm pool support\nimport vm from 'node:vm'\nexport default {\n  name: 'myenv',\n  setup(global, options) { /* ... */ },\n  setupVM(options) {\n    const context = vm.createContext({})\n    return { getVmContext: () => context, teardown() { /* ... */ } }\n  },\n}","handlingStrategy":"type-guard","validationCode":"import type { Environment } from 'vitest'\n\nfunction supportsVm(env: Environment): boolean {\n  return typeof (env as any).setupVM === 'function'\n}\n\n// before opting into vmThreads, check:\nif (pool.startsWith('vm') && !supportsVm(resolvedEnvironment)) {\n  throw new Error(`Environment '${resolvedEnvironment.name}' cannot be used with ${pool}; it lacks setupVM.`)\n}","typeGuard":"type VmCapableEnvironment = Environment & { setupVM: (options: unknown) => { getVmContext: () => unknown } }\n\nfunction isVmCapable(env: Environment): env is VmCapableEnvironment {\n  return typeof (env as any).setupVM === 'function'\n}","tryCatchPattern":null,"preventionTips":["Before switching to vmThreads/vmForks, confirm the environment package documents setupVM support.","When authoring a custom environment, implement both setup and setupVM from the start.","Pin environment package versions that match your vitest major."],"tags":["vm-pool","environment","setupvm","custom-environment"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}