vitest-dev/vitest · error · Error

No property descriptor for ${globalName}, this is a bug in V

Error message

No property descriptor for ${globalName}, this is a bug in Vitest.

What it means

populateNodeGlobals iterates Object.getOwnPropertyNames(globalThis) and immediately calls Object.getOwnPropertyDescriptor for each name. The error fires if getOwnPropertyDescriptor returns undefined for a name that getOwnPropertyNames just returned — a logical impossibility in a single-threaded, stable runtime. The message explicitly says 'this is a bug in Vitest,' signaling an internal invariant violation, likely caused by concurrent modification of globalThis during enumeration.

Source

Thrown at packages/vitest/src/integrations/env/node.ts:32

const nodeGlobals = new Map<string, PropertyDescriptor>()

function populateNodeGlobals() {
  if (nodeGlobals.size !== 0) {
    return
  }

  const names = Object.getOwnPropertyNames(globalThis)
  const length = names.length
  for (let i = 0; i < length; i++) {
    const globalName = names[i]
    if (!denyList.has(globalName)) {
      const descriptor = Object.getOwnPropertyDescriptor(
        globalThis,
        globalName,
      )

      if (!descriptor) {
        throw new Error(
          `No property descriptor for ${globalName}, this is a bug in Vitest.`,
        )
      }
      nodeGlobals.set(globalName, descriptor)
    }
  }
}

export default <Environment>{
  name: 'node',
  viteEnvironment: 'ssr',
  // this is largely copied from jest's node environment
  async setupVM() {
    populateNodeGlobals()

    const vm = await import('node:vm')
    let context = vm.createContext()
    let global = vm.runInContext('this', context)

View on GitHub (pinned to 1fa9837ec2)

Solutions

  1. Identify any code that mutates globalThis during test setup and defer it until after environment initialization.
  2. Update Vitest — newer versions may handle concurrent global mutation more defensively.
  3. If reproducible, file a Vitest bug with the globalThis property name and the mutating library identified.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  // run tests that trigger node environment setup
} catch (e) {
  if (e.message.includes('No property descriptor') && e.message.includes('bug in Vitest')) {
    // report to Vitest; identify globalThis mutator
  } else throw e
}

Prevention

When it happens

Trigger: Another library or a previously-loaded test mutates globalThis (deletes or redefines properties) while populateNodeGlobals is enumerating, so a name returned by getOwnPropertyNames no longer has a descriptor by the time getOwnPropertyDescriptor is called. Also theoretically triggerable by a custom Node build or VM context with non-standard global semantics.

Common situations: Extremely rare. Seen in environments where globalThis is being proxied or heavily mutated (e.g. some sandboxing libraries, polyfills that delete/redefine globals during load). Almost always an environment bug, not a user config issue.

Related errors


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