{"record":{"id":"27931000b9ab87e3","repo":"n8n-io/n8n","slug":"set-operation-is-only-supported-for-many-to-one-an","errorCode":null,"errorMessage":"Set operation is only supported for many-to-one and one-to-one relations. However given \"${relation.propertyPath}\" has ${relation.relationType} relation. Use .add() method instead.","messagePattern":"Set operation is only supported for many-to-one and one-to-one relations\\. However given \"(.+?)\" has (.+?) relation\\. Use \\.add\\(\\) method instead\\.","errorType":"exception","errorClass":"TypeORMError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/typeorm/src/query-builder/RelationQueryBuilder.ts","lineNumber":55,"sourceCode":"\t}\n\n\t/**\n\t * Sets entity relation's value.\n\t * Value can be entity, entity id or entity id map (if entity has composite ids).\n\t * Works only for many-to-one and one-to-one relations.\n\t * For many-to-many and one-to-many relations use #add and #remove methods instead.\n\t */\n\tasync set(value: any): Promise<void> {\n\t\tconst relation = this.expressionMap.relationMetadata;\n\n\t\tif (!this.expressionMap.of)\n\t\t\t// todo: move this check before relation query builder creation?\n\t\t\tthrow new TypeORMError(\n\t\t\t\t`Entity whose relation needs to be set is not set. Use .of method to define whose relation you want to set.`,\n\t\t\t);\n\n\t\tif (relation.isManyToMany || relation.isOneToMany)\n\t\t\tthrow new TypeORMError(\n\t\t\t\t`Set operation is only supported for many-to-one and one-to-one relations. ` +\n\t\t\t\t\t`However given \"${relation.propertyPath}\" has ${relation.relationType} relation. ` +\n\t\t\t\t\t`Use .add() method instead.`,\n\t\t\t);\n\n\t\t// if there are multiple join columns then user must send id map as \"value\" argument. check if he really did it\n\t\tif (\n\t\t\trelation.joinColumns &&\n\t\t\trelation.joinColumns.length > 1 &&\n\t\t\t(!ObjectUtils.isObject(value) || Object.keys(value).length < relation.joinColumns.length)\n\t\t)\n\t\t\tthrow new TypeORMError(\n\t\t\t\t`Value to be set into the relation must be a map of relation ids, for example: .set({ firstName: \"...\", lastName: \"...\" })`,\n\t\t\t);\n\n\t\tconst updater = new RelationUpdater(this, this.expressionMap);\n\t\treturn updater.update(value);\n\t}","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/typeorm/src/query-builder/RelationQueryBuilder.ts#L37-L73","documentation":"RelationQueryBuilder.set supports only many-to-one and one-to-one (the single-valued, FK-on-this-side) relations. If relation.isManyToMany || relation.isOneToMany it throws TypeORMError pointing the developer at .add() instead, because .set would have to overwrite a whole collection which the FK-update strategy it uses cannot express.","triggerScenarios":"Calling .set(newValue) on a @OneToMany or @ManyToMany property, e.g. qb.relation(User,'groups').of(u).set([g1,g2]). The owning side is a collection, so a single assignment is ambiguous.","commonSituations":"Misreading the decorator on the entity; inverse-side confusion (developer thinks the relation is mto but it is otm); copy-pasting a .set() call from a profile relation onto a tags relation.","solutions":["Switch to .add()/.remove() for collection relations: qb.relation(User,'groups').of(u).add([g1,g2]).","Double-check the decorator type on the property named in relation.propertyPath and confirm the relation you intended.","If you truly need to replace the whole collection, fetch current members and .remove() the difference, then .add() new ones inside a transaction."],"exampleFix":"// before\nawait qb.relation(User,'groups').of(u).set([g1, g2]); // groups is many-to-many\n// after\nawait qb.relation(User,'groups').of(u).add([g1, g2]);","handlingStrategy":"type-guard","validationCode":"import { DataSource } from 'typeorm';\n\nfunction isSingleValuedRelation(ds: DataSource, target: Function, path: string): boolean {\n  const r = ds.getMetadata(target).findRelationWithPropertyPath(path);\n  return !!r && (r.relationType === 'many-to-one' || r.relationType === 'one-to-one');\n}\n// if (!isSingleValuedRelation(ds, User, 'profile')) throw ...","typeGuard":"function supportsSet(ds: DataSource, target: Function, path: string): boolean {\n  const r = ds.getMetadata(target).findRelationWithPropertyPath(path);\n  return !!r && (r.isManyToOne || r.isOneToOne);\n}","tryCatchPattern":null,"preventionTips":["Keep a cheat-sheet of which decorator supports which relation-API method next to the entity.","Code-review relation calls for decorator/API agreement.","Encapsulate relation mutations behind a service so the decorator type is checked in one place."],"tags":["typeorm","relation-query-builder","set","relation-type"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}