angular/components · error
ProxyZoneSpec is needed for the test harnesses but could not
Error message
ProxyZoneSpec is needed for the test harnesses but could not be found. Please make sure that your environment includes zone.js/dist/zone-testing.js
What it means
The Component Dev Kit (CDK) test harnesses require zone.js's ProxyZoneSpec to intercept and await async tasks during change detection. This error means Zone['ProxyZoneSpec'] is undefined at runtime because the zone-testing bundle was never loaded. The library throws early in harness setup rather than silently mis-behaving.
Source
Thrown at src/cdk/testing/testbed/task-state-zone-interceptor.ts:85
* Sets up the custom task state Zone interceptor in the `ProxyZone`. Throws if
* no `ProxyZone` could be found.
* @returns an observable that emits whenever the task state changes.
*/
static setup(): Observable<TaskState> {
if (Zone === undefined) {
throw Error(
'Could not find ZoneJS. For test harnesses running in TestBed, ' +
'ZoneJS needs to be installed.',
);
}
// tslint:disable-next-line:variable-name
const ProxyZoneSpec = (Zone as any)['ProxyZoneSpec'] as ProxyZoneStatic | undefined;
// If there is no "ProxyZoneSpec" installed, we throw an error and recommend
// setting up the proxy zone by pulling in the testing bundle.
if (!ProxyZoneSpec) {
throw Error(
'ProxyZoneSpec is needed for the test harnesses but could not be found. ' +
'Please make sure that your environment includes zone.js/dist/zone-testing.js',
);
}
// Ensure that there is a proxy zone instance set up, and get
// a reference to the instance if present.
const zoneSpec = ProxyZoneSpec.assertPresent() as PatchedProxyZone;
// If there already is a delegate registered in the proxy zone, and it
// is type of the custom task state interceptor, we just use that state
// observable. This allows us to only intercept Zone once per test
// (similar to how `fakeAsync` or `async` work).
if (zoneSpec[stateObservableSymbol]) {
return zoneSpec[stateObservableSymbol]!;
}
// Since we intercept on environment creation and the fixture has beenView on GitHub (pinned to 0411926e7d)
Solutions
- Add 'node_modules/zone.js/dist/zone-testing.js' (zone.js < 0.11) or 'node_modules/zone.js/plugins/zone-testing' to the 'files'/'testFiles' list in angular.json, karma.conf.js, or your Jest/Vitest setup
- Verify Zone is actually loaded before harnesses: import 'zone.js' first, then zone-testing
- If using zone.js >= 0.11, update the old dist/ path which silently fails to register ProxyZoneSpec
- If the app is intentionally zoneless, load zone-testing in the test setup only, or use the harness-free querying APIs
Example fix
// before (angular.json)
"test": { "options": { "src": ["test.ts"] } }
// karma.conf.ts files: missing zone-testing
// after
"files": [
"node_modules/zone.js/dist/zone.js",
"node_modules/zone.js/dist/zone-testing.js"
] Defensive patterns
Strategy: validation
Validate before calling
if (!(Zone as any)?.['ProxyZoneSpec']) {
throw new Error('zone.js/dist/zone-testing.js is not loaded; harnesses cannot run');
}
// or check before creating harnesses in a shared test util:
expect((Zone as any)['ProxyZoneSpec']).toBeTruthy(); Type guard
const hasProxyZone = (): boolean => typeof Zone !== 'undefined' && !!(Zone as any)['ProxyZoneSpec'];
Try / catch
try {
await loader.getHarness(MyHarness);
} catch (e) {
if ((e as Error).message.includes('ProxyZoneSpec is needed')) {
fail('Add zone.js/dist/zone-testing.js to your test setup');
}
throw e;
} Prevention
- Include zone-testing in the shared test entry file so every spec has it
- After upgrading zone.js, verify the bundle path (dist/ vs plugins/)
- Add a smoke test that asserts ProxyZoneSpec exists before any harness use
- Keep harness setup utilities in one place to centralize the zone requirement
When it happens
Trigger: Calling any TestbedHarnessEnvironment API (e.g. loader(), harnessForFixture) or creating a harness whose setup path reaches TaskStateZoneInterceptor.setup when zone.js/dist/zone-testing.js (or zone.js/plugins/zone-testing for newer versions) is not included in test files.
Common situations: Missing zone-testing.js entry in angular.json test file globs; switching from Karma to Jest/Vitest without loading zone testing manually; upgrading Angular/zone.js where the dist path changed (zone.js/dist/zone-testing.js -> zone.js/plugins/zone-testing.js in zone.js >= 0.11); running with zoneless/noop Zone config while harnesses still expect zone.
Related errors
- Cannot retrieve popup content because the combobox is closed
- Could not find tab matching filters: ${JSON.stringify(filter
- Cannot read "${filePath}" because it does not exist.
- Project name is required.
- Unable to retrieve options for autocomplete. Autocomplete pa
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/f45fb004da436146.
Report an issue: GitHub.