angular/angular · error · Error
Missing ProxyZoneSpec
Error message
Missing ProxyZoneSpec
What it means
The vitest patch needs ProxyZoneSpec to create the proxy zone that isolates each vitest test's zone state. It checks Zone.ProxyZoneSpec right after marking vitest with __zone_patch__; if the proxy zone-spec module was never loaded, the property is undefined and it throws. Loading zone.js for vitest therefore requires the proxy spec to have been registered first.
Source
Thrown at packages/zone.js/lib/vitest/vitest.ts:61
*/
const CURRIED_MODIFIER_NAMES = ['skipIf', 'runIf', 'each', 'for'] as const;
type TEST_MODIFIER_NAME = (typeof DIRECT_MODIFIER_NAMES | typeof CURRIED_MODIFIER_NAMES)[number];
export function patchVitest(Zone: ZoneType): void {
Zone.__load_patch('vitest', (context: any, Zone: TestingZoneType) => {
// Vitest global variable set by the Vitest runner during test execution
const vitestGlobal = context['vitest'] as {['__zone_patch__']?: boolean} | undefined;
// Skip patching if vitest is not present or has already been patched
if (typeof vitestGlobal === 'undefined' || vitestGlobal['__zone_patch__']) {
return;
}
vitestGlobal['__zone_patch__'] = true;
// Ensure other testing related Zone.js patches have been applied
if (!Zone.ProxyZoneSpec) {
throw new Error('Missing ProxyZoneSpec');
}
if (!Zone.SyncTestZoneSpec) {
throw new Error('Missing SyncTestZoneSpec');
}
// Setup testing related Zone instances
const rootZone = Zone.current;
const syncZone = rootZone.fork(new Zone.SyncTestZoneSpec('vitest.describe'));
const proxyZone = rootZone.fork(new Zone.ProxyZoneSpec());
/**
* Gets a function wrapping the body of a vitest `describe` block to execute in a
* synchronous-only zone.
*/
function wrapDescribeInZone(describeBody: Function): Function {
// `describe` might be called without a body (e.g. `describe.todo`)
if (typeof describeBody !== 'function') {
return describeBody;View on GitHub (pinned to 51cb07e980)
Solutions
- In vitest setupFiles, load the proxy spec before the vitest patch: import 'zone.js/lib/zone-spec/proxy' then 'zone.js/lib/vitest/vitest' (or the zone-testing equivalent that already contains it)
- Prefer the documented Angular vitest setup which wires the correct zone.js bundles
- After setup, assert (globalThis.Zone as any).ProxyZoneSpec is truthy in a smoke test
Example fix
// before (vitest.setup.ts) import 'zone.js/lib/vitest/vitest'; // ProxyZoneSpec not yet registered // after import 'zone.js/lib/zone-spec/proxy'; import 'zone.js/lib/zone-spec/sync-test'; import 'zone.js/lib/vitest/vitest';
Defensive patterns
Strategy: validation
Validate before calling
// vitest setupFiles, ordered imports
import 'zone.js/lib/zone-spec/proxy';
import 'zone.js/lib/zone-spec/sync-test';
import 'zone.js/lib/vitest/vitest';
if (!(globalThis.Zone as any).ProxyZoneSpec) throw new Error('proxy spec missing'); Type guard
const hasProxyZoneSpec = (z: any): boolean => typeof z?.ProxyZoneSpec === 'function';
Prevention
- Use the documented Angular vitest zone preset instead of hand-rolled patch imports
- Keep zone-related imports together at the top of a single setup file
When it happens
Trigger: Setting up zone.js with vitest by loading only a vitest-specific patch file without 'zone.js/lib/zone-spec/proxy'; using a custom entry like zone-vitest.js that omits the proxy spec; importing the vitest patch before the proxy module. Fires only when global.vitest exists (inside a vitest run).
Common situations: Adopting vitest with Angular/zone-based code and hand-rolling the zone setup in vitest setupFiles instead of using the documented preset; partial migration where jest setup files are reused; tree-shaking or selective imports trimming the proxy spec out of the bundle.
Related errors
- Missing ProxyZoneSpec
- Missing SyncTestZoneSpec
- ProxyZoneSpec is needed for the async() test helper but coul
- Missing: ProxyZoneSpec
- Missing ProxyZoneSpec
AI-assisted analysis of angular/angular@51cb07e980 (2026-08-22).
Data as JSON: /api/errors/802ca8f39ff2a178.
Report an issue: GitHub.