n8n-io/n8n · error · CircularRelationsError
Circular relations detected: ${path}. To resolve this issue
Error message
Circular relations detected: ${path}. To resolve this issue you need to set nullable: true somewhere in this dependency structure. What it means
TypeORM builds a dependency graph where each non-nullable join-column relation adds an edge from the entity to its inverse, then calls `graph.overallOrder()` to topologically sort entities for INSERT ordering. If the sort reports a dependency cycle, `CircularRelationsError` is thrown: two or more entities mutually require each other through NOT NULL foreign keys, so none can be inserted first.
Source
Thrown at packages/@n8n/typeorm/src/metadata-builder/EntityMetadataValidator.ts:266
/**
* Validates dependencies of the entity metadatas.
*/
protected validateDependencies(entityMetadatas: EntityMetadata[]) {
const graph = new DepGraph();
entityMetadatas.forEach((entityMetadata) => {
graph.addNode(entityMetadata.name);
});
entityMetadatas.forEach((entityMetadata) => {
entityMetadata.relationsWithJoinColumns
.filter((relation) => !relation.isNullable)
.forEach((relation) => {
graph.addDependency(entityMetadata.name, relation.inverseEntityMetadata.name);
});
});
try {
graph.overallOrder();
} catch (err) {
throw new CircularRelationsError(
err.toString().replace('Error: Dependency Cycle Found: ', ''),
);
}
}
/**
* Validates eager relations to prevent circular dependency in them.
*/
protected validateEagerRelations(entityMetadatas: EntityMetadata[]) {
entityMetadatas.forEach((entityMetadata) => {
entityMetadata.eagerRelations.forEach((relation) => {
if (relation.inverseRelation && relation.inverseRelation.isEager)
throw new TypeORMError(
`Circular eager relations are disallowed. ` +
`${entityMetadata.targetName}#${relation.propertyPath} contains "eager: true", and its inverse side ` +
`${relation.inverseEntityMetadata.targetName}#${relation.inverseRelation.propertyPath} contains "eager: true" as well.` +
` Remove "eager: true" from one side of the relation.`,
);View on GitHub (pinned to 5ac6606e81)
Solutions
- Set `nullable: true` on at least one join column in the cycle (the error message's own guidance) so TypeORM can insert, then update the FK in a second step.
- Break the cycle in application code: insert parent without FK, then UPDATE the FK once the child exists.
- Use a junction table (@ManyToMany) for the mutual dependency so neither side carries a mandatory FK.
Example fix
// before — both sides NOT NULL → cycle
@ManyToOne(() => B, { nullable: false }) b: B;
@ManyToOne(() => A, { nullable: false }) a: A;
// after — break the cycle
@ManyToOne(() => B, { nullable: true }) b: B | null; Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: detect cycles among non-nullable join-column relations
const deps = new Map<string, string[]>();
for (const m of dataSource.entityMetadatas) deps.set(m.name, []);
for (const m of dataSource.entityMetadatas) {
for (const r of m.relationsWithJoinColumns) {
if (!r.isNullable) deps.get(m.name)!.push(r.inverseEntityMetadata.name);
}
}
// run a DFS cycle check on `deps` before calling initialize's schema build Try / catch
try { await dataSource.initialize(); } catch (e) { if (e instanceof CircularRelationsError) { console.error('Cycle path:', e.message); } throw e; } Prevention
- Make at least one join column in any mutual dependency `nullable: true`.
- Insert co-dependent entities in two steps (parent first, then UPDATE the FK).
- Use junction tables for truly mutual relationships.
When it happens
Trigger: Entities A and B each carry a `@ManyToOne(() => Other, { nullable: false })` pointing at the other (or a longer cycle A->B->C->A) with all join columns non-nullable. Defining `@JoinColumn({ nullable: false })` on both sides of a mutual relation.
Common situations: Modeling a two-way mandatory ownership (user must have a profile, profile must have a user) where neither side is allowed null. Forgetting `nullable: true` on at least one side of a co-dependent pair.
Related errors
- OnUpdateType "${relation.onUpdate}" is not valid for ${drive
- Relation ${entityMetadata.name}#${relation.propertyName} and
- Circular eager relations are disallowed. ${entityMetadata.ta
- Referenced column ${joinColumn.referencedColumnName} was not
- Referenced column ${joinColumn.referencedColumnName} was not
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/351abce92def5ca9.
Report an issue: GitHub.