Skip to content

Commit bb65520

Browse files
SkyZeroZxAndrewKushnir
authored andcommitted
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 angular#65968
1 parent 5f01f12 commit bb65520

4 files changed

Lines changed: 102 additions & 2 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Circular Dependency Detected
2+
3+
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.
4+
5+
This circular reference prevents Angular from properly initializing the components, resulting in an error like:
6+
7+
```text
8+
NG0919: Cannot read @Component metadata. This can indicate a runtime circular dependency in your app that needs to be resolved.
9+
```
10+
11+
In older Angular versions, you might instead see an error like:
12+
13+
```text
14+
Cannot read properties of undefined (reading 'ɵcmp')
15+
```
16+
17+
## Common Causes
18+
19+
### Mutual Component Imports
20+
21+
The most common cause is when two components import each other:
22+
23+
```angular-ts {header:"parent.component.ts"}
24+
import {Component} from '@angular/core';
25+
import {ChildComponent} from './child.component';
26+
27+
@Component({
28+
selector: 'app-parent',
29+
imports: [ChildComponent],
30+
template: '<app-child/>',
31+
})
32+
export class ParentComponent {}
33+
```
34+
35+
```angular-ts {header:"child.component.ts"}
36+
import {Component} from '@angular/core';
37+
import {ParentComponent} from './parent.component';
38+
39+
@Component({
40+
selector: 'app-child',
41+
imports: [ParentComponent],
42+
template: '<app-parent/>',
43+
})
44+
export class ChildComponent {}
45+
```
46+
47+
### Indirect Circular References
48+
49+
Circular dependencies can also occur through intermediate files:
50+
51+
```text
52+
ComponentA -> ComponentB -> ComponentC -> ComponentA
53+
```
54+
55+
## Resolving the error
56+
57+
### Refactor shared logic
58+
59+
Move shared functionality to a separate file that doesn't import either component:
60+
61+
```angular-ts {header:"shared.service.ts"}
62+
import {Injectable} from '@angular/core';
63+
64+
@Injectable({providedIn: 'root'})
65+
export class SharedService {
66+
// Shared logic here
67+
}
68+
```
69+
70+
### Use type-only imports
71+
72+
If you only need types for TypeScript, use `import type`:
73+
74+
```ts
75+
import type {ParentComponent} from './parent.component';
76+
```
77+
78+
Type-only imports are erased at compile time and don't contribute to runtime circular dependencies.
79+
80+
### Restructure component hierarchy
81+
82+
Consider whether the circular dependency indicates a design issue. Often, extracting shared functionality into a third component or service is the cleanest solution.
83+
84+
### Debugging complex circular dependencies
85+
86+
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:
87+
88+
```bash
89+
# Install madge
90+
npm install -g madge
91+
92+
# Check for circular dependencies
93+
madge --circular --extensions ts ./src
94+
95+
# Generate a visual graph
96+
madge --circular --extensions ts --image graph.svg ./src
97+
```
98+
99+
These tools can help identify circular dependency chains across your entire project and generate visual dependency graphs.

adev/src/content/reference/errors/overview.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
| `NG0750` | [@defer dependencies failed to load](errors/NG0750) |
2626
| `NG0910` | [Unsafe bindings on an iframe element](errors/NG0910) |
2727
| `NG0912` | [Component ID generation collision](errors/NG0912) |
28+
| `NG0919` | [Circular Dependency Detected](errors/NG0919) |
2829
| `NG0955` | [Track expression resulted in duplicated keys for a given collection](errors/NG0955) |
2930
| `NG0956` | [Tracking expression caused re-creation of the DOM structure](errors/NG0956) |
3031
| `NG01101` | [Wrong Async Validator Return Type](errors/NG01101) |

goldens/public-api/core/errors.api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const enum RuntimeErrorCode {
3434
// (undocumented)
3535
CYCLIC_DI_DEPENDENCY = -200,
3636
// (undocumented)
37-
DEF_TYPE_UNDEFINED = 919,
37+
DEF_TYPE_UNDEFINED = -919,
3838
// (undocumented)
3939
DEFER_IN_HMR_MODE = -751,
4040
// (undocumented)

packages/core/src/errors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export const enum RuntimeErrorCode {
134134
MISSING_DIRECTIVE_DEFINITION = 916,
135135
NO_COMPONENT_FACTORY_FOUND = 917,
136136
EXTERNAL_RESOURCE_LOADING_FAILED = 918,
137-
DEF_TYPE_UNDEFINED = 919,
137+
DEF_TYPE_UNDEFINED = -919,
138138

139139
// Signal integration errors
140140
REQUIRED_INPUT_NO_VALUE = -950,

0 commit comments

Comments
 (0)