docs: Adds documentation for the NG0919 error

Adds a new documentation page for the NG0919 error, which indicates a circular dependency in Angular applications.

fixes  #65968
This commit is contained in:
SkyZeroZx 2025-12-14 12:10:48 -05:00 committed by Andrew Kushnir
parent 5f01f121df
commit bb65520991
4 changed files with 102 additions and 2 deletions

View file

@ -0,0 +1,99 @@
# Circular Dependency Detected
Angular detected a circular dependency between components, directives, or pipes. This error occurs when component A imports component B, and component B (directly or indirectly) imports component A, creating a cycle.
This circular reference prevents Angular from properly initializing the components, resulting in an error like:
```text
NG0919: Cannot read @Component metadata. This can indicate a runtime circular dependency in your app that needs to be resolved.
```
In older Angular versions, you might instead see an error like:
```text
Cannot read properties of undefined (reading 'ɵcmp')
```
## Common Causes
### Mutual Component Imports
The most common cause is when two components import each other:
```angular-ts {header:"parent.component.ts"}
import {Component} from '@angular/core';
import {ChildComponent} from './child.component';
@Component({
selector: 'app-parent',
imports: [ChildComponent],
template: '<app-child/>',
})
export class ParentComponent {}
```
```angular-ts {header:"child.component.ts"}
import {Component} from '@angular/core';
import {ParentComponent} from './parent.component';
@Component({
selector: 'app-child',
imports: [ParentComponent],
template: '<app-parent/>',
})
export class ChildComponent {}
```
### Indirect Circular References
Circular dependencies can also occur through intermediate files:
```text
ComponentA -> ComponentB -> ComponentC -> ComponentA
```
## Resolving the error
### Refactor shared logic
Move shared functionality to a separate file that doesn't import either component:
```angular-ts {header:"shared.service.ts"}
import {Injectable} from '@angular/core';
@Injectable({providedIn: 'root'})
export class SharedService {
// Shared logic here
}
```
### Use type-only imports
If you only need types for TypeScript, use `import type`:
```ts
import type {ParentComponent} from './parent.component';
```
Type-only imports are erased at compile time and don't contribute to runtime circular dependencies.
### Restructure component hierarchy
Consider whether the circular dependency indicates a design issue. Often, extracting shared functionality into a third component or service is the cleanest solution.
### Debugging complex circular dependencies
For complex applications with many modules, circular dependencies can be difficult to identify manually. Consider using tools like [madge](https://www.npmjs.com/package/madge) to visualize and detect circular imports:
```bash
# Install madge
npm install -g madge
# Check for circular dependencies
madge --circular --extensions ts ./src
# Generate a visual graph
madge --circular --extensions ts --image graph.svg ./src
```
These tools can help identify circular dependency chains across your entire project and generate visual dependency graphs.

View file

@ -25,6 +25,7 @@
| `NG0750` | [@defer dependencies failed to load](errors/NG0750) |
| `NG0910` | [Unsafe bindings on an iframe element](errors/NG0910) |
| `NG0912` | [Component ID generation collision](errors/NG0912) |
| `NG0919` | [Circular Dependency Detected](errors/NG0919) |
| `NG0955` | [Track expression resulted in duplicated keys for a given collection](errors/NG0955) |
| `NG0956` | [Tracking expression caused re-creation of the DOM structure](errors/NG0956) |
| `NG01101` | [Wrong Async Validator Return Type](errors/NG01101) |

View file

@ -34,7 +34,7 @@ export const enum RuntimeErrorCode {
// (undocumented)
CYCLIC_DI_DEPENDENCY = -200,
// (undocumented)
DEF_TYPE_UNDEFINED = 919,
DEF_TYPE_UNDEFINED = -919,
// (undocumented)
DEFER_IN_HMR_MODE = -751,
// (undocumented)

View file

@ -134,7 +134,7 @@ export const enum RuntimeErrorCode {
MISSING_DIRECTIVE_DEFINITION = 916,
NO_COMPONENT_FACTORY_FOUND = 917,
EXTERNAL_RESOURCE_LOADING_FAILED = 918,
DEF_TYPE_UNDEFINED = 919,
DEF_TYPE_UNDEFINED = -919,
// Signal integration errors
REQUIRED_INPUT_NO_VALUE = -950,