angular/angular-cli · error · SchematicsException
Tree type is not supported.
Error message
Tree type is not supported.
What it means
The filter() rule only knows how to apply a FilePredicate to a HostTree. If the tree passed at execution time is not a HostTree (checked via HostTree.isHostTree), the rule cannot construct a FilterHostTree and throws SchematicsException. It protects against silently filtering trees with incompatible semantics.
Source
Thrown at packages/angular_devkit/schematics/src/rules/base.ts:80
export function mergeWith(source: Source, strategy: MergeStrategy = MergeStrategy.Default): Rule {
return (tree, context) => {
return callSource(source, context).pipe(
map((sourceTree) => tree.merge(sourceTree, strategy || context.strategy)),
mapTo(tree),
);
};
}
export function noop(): Rule {
return () => {};
}
export function filter(predicate: FilePredicate<boolean>): Rule {
return (tree: Tree) => {
if (HostTree.isHostTree(tree)) {
return new FilterHostTree(tree, predicate);
} else {
throw new SchematicsException('Tree type is not supported.');
}
};
}
export function asSource(rule: Rule): Source {
return (context) => callRule(rule, staticEmpty(), context);
}
export function branchAndMerge(rule: Rule, strategy: MergeStrategy = MergeStrategy.Default): Rule {
return (tree, context) => {
return callRule(rule, tree.branch(), context).pipe(
map((branch) => tree.merge(branch, strategy || context.strategy)),
mapTo(tree),
);
};
}
export function when(predicate: FilePredicate<boolean>, operator: FileOperator): FileOperator {View on GitHub (pinned to bb72145f9a)
Solutions
- Ensure the tree is a HostTree — operate on the underlying host tree instead of a custom Tree.
- Replace filter() with manual visit/delete logic that works on any Tree implementation.
- If wrapping trees (e.g. in a UnitTestTree), pass the underlying HostTree (tree.branch() or host access).
Example fix
// before
return filter(p => p)(tree as any);
// after
if (!HostTree.isHostTree(tree)) { /* manual filtering */ }
return (t: Tree) => t.visit(p => { if (!predicate(p)) { t.delete(p.path); } }); Defensive patterns
Strategy: type-guard
Validate before calling
import { HostTree } from '@angular-devkit/schematics';
if (!HostTree.isHostTree(tree)) {
throw new Error('filter() requires a HostTree');
} Type guard
function isHostTree(t: Tree): t is HostTree {
return HostTree.isHostTree(t);
} Try / catch
try {
return applyRules([filter(predicate)], tree);
} catch (err) {
if (err.message.includes('Tree type is not supported')) {
// fall back to manual visit/delete filtering
}
} Prevention
- Only call filter() on HostTree-based trees.
- Prefer manual tree.visit + tree.delete for custom Tree implementations.
- Avoid exotic Tree wrappers inside filter pipelines.
When it happens
Trigger: Using filter(predicate) inside a rule that receives a custom Tree implementation (e.g. a wrapped/subclassed tree or a FilterHostTree-hostile tree from another engine/adapter).
Common situations: Custom Tree implementations from third-party tooling; using filter on a tree produced via applyToSubtree with an exotic host; library versions where a custom host was introduced.
Related errors
- Original tree must be returned from all rules when using "ap
- Pipe "${pipe}" is invalid.
- A merge conflicted on path "${path}".
- Path "${record instanceof UpdateRecorderBase ? record.path :
- Cannot create file "${path}".
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/7586be0b7db05095.
Report an issue: GitHub.