{"record":{"id":"f9622e0a5ef1e38a","repo":"n8n-io/n8n","slug":"circular-eager-relations-are-disallowed-entitym","errorCode":null,"errorMessage":"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.","messagePattern":"Circular eager relations are disallowed\\. (.+?)#(.+?) contains \"eager: true\", and its inverse side (.+?)#(.+?) contains \"eager: true\" as well\\. Remove \"eager: true\" from one side of the relation\\.","errorType":"exception","errorClass":"TypeORMError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/typeorm/src/metadata-builder/EntityMetadataValidator.ts","lineNumber":279,"sourceCode":"\t\t\t\t});\n\t\t});\n\t\ttry {\n\t\t\tgraph.overallOrder();\n\t\t} catch (err) {\n\t\t\tthrow new CircularRelationsError(\n\t\t\t\terr.toString().replace('Error: Dependency Cycle Found: ', ''),\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Validates eager relations to prevent circular dependency in them.\n\t */\n\tprotected validateEagerRelations(entityMetadatas: EntityMetadata[]) {\n\t\tentityMetadatas.forEach((entityMetadata) => {\n\t\t\tentityMetadata.eagerRelations.forEach((relation) => {\n\t\t\t\tif (relation.inverseRelation && relation.inverseRelation.isEager)\n\t\t\t\t\tthrow new TypeORMError(\n\t\t\t\t\t\t`Circular eager relations are disallowed. ` +\n\t\t\t\t\t\t\t`${entityMetadata.targetName}#${relation.propertyPath} contains \"eager: true\", and its inverse side ` +\n\t\t\t\t\t\t\t`${relation.inverseEntityMetadata.targetName}#${relation.inverseRelation.propertyPath} contains \"eager: true\" as well.` +\n\t\t\t\t\t\t\t` Remove \"eager: true\" from one side of the relation.`,\n\t\t\t\t\t);\n\t\t\t});\n\t\t});\n\t}\n}\n","sourceCodeStart":261,"sourceCodeEnd":289,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/typeorm/src/metadata-builder/EntityMetadataValidator.ts#L261-L289","documentation":"TypeORM rejects relations where BOTH sides are marked `eager: true`. Eager loading pulls the related rows on every fetch of the parent; if each side is eager, loading A would load B which would eagerly load A again, recursing without end. The validator scans `entityMetadata.eagerRelations` and throws when an inverse relation is also eager.","triggerScenarios":"Two entities with a bidirectional @OneToMany/@ManyToOne or @ManyToMany where both decorators carry `eager: true`. A @OneToOne with `eager: true` on the owner and also on the inverse.","commonSituations":"Adding `eager: true` to make 'the relation always loads' on both ends for convenience. Copying an eager relation to its inverse during a refactor.","solutions":["Remove `eager: true` from one side; keep eager only on the side you most often traverse.","Better: drop `eager` entirely and load relations explicitly via `relations: [...]` in find options or QueryBuilder `leftJoinAndSelect`.","Use `relation.load()` (lazy relation) on the side you rarely need."],"exampleFix":"// before\n@OneToMany(() => Order, o => o.customer, { eager: true }) orders: Order[];\n@ManyToOne(() => Customer, c => c.orders, { eager: true }) customer: Customer;\n\n// after — eager on one side only\n@OneToMany(() => Order, o => o.customer, { eager: true }) orders: Order[];\n@ManyToOne(() => Customer, c => c.orders) customer: Customer;","handlingStrategy":"validation","validationCode":"for (const m of dataSource.entityMetadatas) {\n  for (const r of m.eagerRelations) {\n    if (r.inverseRelation?.isEager) {\n      throw new Error(`Mutual eager: ${m.name}#${r.propertyName} <-> ${r.inverseRelation.entityMetadata.name}`);\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try { await dataSource.initialize(); } catch (e) { if (e instanceof TypeORMError && /Circular eager relations/) { /* drop eager:true from one side */ } throw e; }","preventionTips":["Default to non-eager relations and load explicitly via `relations`/`leftJoinAndSelect`.","If you use `eager: true`, place it on one side only — the side you traverse most.","Add a lint/review rule: any PR adding `eager: true` must justify it."],"tags":["typeorm","relations","eager-loading","schema-validation","performance"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}