angular/components · error
Unable to read directory in virtual file system host. This m
Error message
Unable to read directory in virtual file system host. This means that TypeScript changed its file matching internals. Please consider downgrading your TypeScript version, and report an issue in the Angular Components repository.
What it means
Internal CDK schematics error thrown by the virtual file system host used by the ng-update tooling. The schematic relies on TypeScript's internal ts.matchFiles API to emulate directory reads; if TypeScript no longer exposes matchFiles, the tool cannot work and asks users to downgrade TypeScript and report the issue.
Source
Thrown at src/cdk/schematics/update-tool/utils/virtual-host.ts:72
readFile(path: string): string | undefined {
const content = this._fileSystem.read(this._fileSystem.resolve(path));
if (content === null) {
return undefined;
}
// Strip BOM as otherwise TSC methods (e.g. "getWidth") will return an offset which
// which breaks the CLI UpdateRecorder. https://github.com/angular/angular/pull/30719
return content.replace(/^\uFEFF/, '');
}
readDirectory(
rootDir: string,
extensions: string[],
excludes: string[] | undefined,
includes: string[],
depth?: number,
): string[] {
if (ts.matchFiles === undefined) {
throw Error(
'Unable to read directory in virtual file system host. This means that ' +
'TypeScript changed its file matching internals.\n\nPlease consider downgrading your ' +
'TypeScript version, and report an issue in the Angular Components repository.',
);
}
return ts.matchFiles(
rootDir,
extensions,
extensions,
includes,
this.useCaseSensitiveFileNames,
'/',
depth,
p => this._getFileSystemEntries(p),
p => this._fileSystem.resolve(p),
p => this._fileSystem.directoryExists(this._fileSystem.resolve(p)),
);
}View on GitHub (pinned to 0411926e7d)
Solutions
- Downgrade TypeScript to a version compatible with your @angular/cdk version (see the CDK's peer dependency on typescript)
- Update @angular/cdk / @angular/cli to a newer release that supports your TypeScript version
- Pin the typescript version in package.json (e.g. "typescript": "~5.4.0") while running the migration
- Report the issue on the Angular Components repository so the tooling can be adapted
Example fix
// before (package.json)
"devDependencies": { "typescript": "^5.9.0" }
// after (package.json)
"devDependencies": { "typescript": "~5.4.0" } Defensive patterns
Strategy: fallback
Validate before calling
import * as ts from 'typescript';
if (typeof (ts as any).matchFiles !== 'function') {
throw new Error(`TypeScript ${ts.version} is incompatible with @angular/cdk migration tooling; downgrade TypeScript.`);
} Type guard
function supportsMatchFiles(ts: typeof import('typescript')): boolean {
return typeof (ts as unknown as { matchFiles?: unknown }).matchFiles === 'function';
} Try / catch
try {
await runMigration(context);
} catch (e) {
if (e instanceof Error && e.message.includes('virtual file system host')) {
console.error('TypeScript version incompatible with CDK schematics. Pin typescript to the version in @angular/cdk peerDependencies.');
} else {
throw e;
}
} Prevention
- Keep the typescript version within the peer dependency range of @angular/cdk
- Pin (not range) the typescript version while running ng update migrations
- Run migrations before major TypeScript upgrades
- Check the Angular Components repo release notes for supported TypeScript versions
When it happens
Trigger: Running ng update / an Angular Components migration schematic with a TypeScript version whose internal API no longer includes ts.matchFiles (TypeScript changed its file-matching internals).
Common situations: Upgrading TypeScript to a version incompatible with the schematics package; running migrations in a repo with a much newer TypeScript than the Angular CDK version supports; using a custom TypeScript build/fork without matchFiles.
Related errors
- Could not find file for path: ${path}
- Attempting to attach an unknown Portal type. BasePortalOutle
- Could not find '<head>' element in HTML file: ${htmlFileBuff
- Could not find <body> element in HTML file: ${htmlFileBuffer
- ListKeyManager constructed with a signal must receive an inj
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/ef79d9028148e66b.
Report an issue: GitHub.