{"record":{"id":"b5b343d09f225b96","repo":"angular/angular-cli","slug":"invalid-rule-result-gettypeofresult-value","errorCode":null,"errorMessage":"Invalid rule result: ${_getTypeOfResult(value)}.","messagePattern":"Invalid rule result: (.+?)\\.","errorType":"exception","errorClass":"InvalidRuleResultException","httpStatus":null,"severity":"error","filePath":"packages/angular_devkit/schematics/src/rules/call.ts","lineNumber":97,"sourceCode":"\n  while (typeof result === 'function') {\n    // This is considered a Rule, chain the rule and return its output.\n    result = await result(tree, context);\n  }\n\n  if (typeof result === 'undefined') {\n    return tree;\n  }\n\n  if (isObservable(result)) {\n    result = await lastValueFrom(result.pipe(defaultIfEmpty(tree)));\n  }\n\n  if (result && TreeSymbol in result) {\n    return result;\n  }\n\n  throw new InvalidRuleResultException(result);\n}\n","sourceCodeStart":79,"sourceCodeEnd":99,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular_devkit/schematics/src/rules/call.ts#L79-L99","documentation":"callRule (async path) requires every Rule to return a Tree, an Observable<Tree>, or void/undefined for in-place mutation. When the rule's resolved result is a truthy value that is not a Tree (no TreeSymbol), InvalidRuleResultException is thrown. It enforces the Rule return contract.","triggerScenarios":"A Rule returning something other than Tree|Observable<Tree>|void — e.g. returning a string, a FileEntry, a Promise of a non-tree, or an object literal.","commonSituations":"Custom rules that accidentally `return tree.visit(...)` (returns void/false-y data), `return someOtherCall()` leaking a non-tree, or TypeScript types bypassed with `as any`.","solutions":["Return the input tree from the rule (or nothing) so the contract Tree|Observable<Tree>|void is met.","If you need async work, return an Observable<Tree> (e.g. from(callRule(...))) not a Promise of another value.","Remove accidental returns: wrap the value-producing call in a statement without returning it."],"exampleFix":"// before\nreturn (tree: Tree) => tree.visit(f => log(f.path)); // visit returns void-ish, not a Tree\n// after\nreturn (tree: Tree) => { tree.visit(f => log(f.path)); return tree; };","handlingStrategy":"type-guard","validationCode":"function ensureRuleResult(v: unknown): Tree | Observable<Tree> | void {\n  if (v === undefined) return v;\n  if (v && typeof v === 'object' && TreeSymbol in (v as object)) return v as Tree;\n  throw new Error('Rule must return Tree | Observable<Tree> | void');\n}","typeGuard":"function isRuleResult(v: unknown): v is Tree | Observable<Tree> | undefined {\n  return v === undefined || (typeof v === 'object' && v !== null && (TreeSymbol in (v as object) || typeof (v as any).subscribe === 'function'));\n}","tryCatchPattern":"try {\n  await firstValueFrom(callRule(myRule, tree, context));\n} catch (err) {\n  if (err instanceof InvalidRuleResultException) {\n    console.error('Rule returned a non-Tree value:', err.message);\n  }\n}","preventionTips":["Annotate rules with the Rule type so wrong returns fail at compile time.","Avoid `return tree.visit(...)` and other accidental non-Tree returns.","For async work return Observable<Tree>, not Promise<other>."],"tags":["schematics","rule","invalid-return-type"],"backgroundTag":"invalid-return-type","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}