{"record":{"id":"b72e08bbe50627ab","repo":"n8n-io/n8n","slug":"value-to-be-set-into-the-relation-must-be-a-map-of","errorCode":null,"errorMessage":"Value to be set into the relation must be a map of relation ids, for example: .set({ firstName: \"...\", lastName: \"...\" })","messagePattern":"Value to be set into the relation must be a map of relation ids, for example: \\.set\\((.+?)\\)","errorType":"exception","errorClass":"TypeORMError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/typeorm/src/query-builder/RelationQueryBuilder.ts","lineNumber":67,"sourceCode":"\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}\n\n\t/**\n\t * Adds (binds) given value to entity relation.\n\t * Value can be entity, entity id or entity id map (if entity has composite ids).\n\t * Value also can be array of entities, array of entity ids or array of entity id maps (if entity has composite ids).\n\t * Works only for many-to-many and one-to-many relations.\n\t * For many-to-one and one-to-one use #set method instead.\n\t */\n\tasync add(value: any | any[]): Promise<void> {\n\t\tif (Array.isArray(value) && value.length === 0) return;\n\n\t\tconst relation = this.expressionMap.relationMetadata;","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/typeorm/src/query-builder/RelationQueryBuilder.ts#L49-L85","documentation":"Inside RelationQueryBuilder.set, when relation.joinColumns.length > 1 (a composite FK), the value argument must be an object map with at least one key per join column. If ObjectUtils.isObject(value) is false or the key count is less than the join-column count, TypeORM throws TypeORMError showing the expected shape .set({ firstName:'...', lastName:'...' }).","triggerScenarios":"Calling .set(singleId) on a relation whose join uses composite keys (e.g. a relation keyed by (tenantId, userId)). Passing an array or a primitive where a partial-object map is required.","commonSituations":"Composite-key entities introduced after the call site was written; tenant-scoped tables where every relation carries tenantId in the FK; passing a bare id from a request param instead of {tenantId, userId}.","solutions":["Pass a map covering every referenced column: qb.relation(...).of(u).set({ tenantId, userId }).","Inspect relation.joinColumns (or its referencedColumn.propertyName) at design time to enumerate the required keys.","If the caller only has one id, fetch the related entity first and pass its composite id map."],"exampleFix":"// before\nqb.relation(Membership,'user').of(m).set(userId); // join uses (tenantId,userId)\n// after\nqb.relation(Membership,'user').of(m).set({ tenantId, userId });","handlingStrategy":"type-guard","validationCode":"import { DataSource } from 'typeorm';\n\nfunction compositeKeys(ds: DataSource, target: Function, path: string): string[] {\n  const r = ds.getMetadata(target).findRelationWithPropertyPath(path)!;\n  return r.joinColumns.map((c: any) => c.referencedColumn!.propertyName);\n}\n// const keys = compositeKeys(ds, Membership, 'user');\n// if (Object.keys(value).length < keys.length) throw new Error(`need keys ${keys.join(',')}`);","typeGuard":"function isCompositeValueMap(value: unknown, keys: string[]): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && keys.every((k) => k in value);\n}","tryCatchPattern":null,"preventionTips":["For composite-FK relations, document the required map shape in JSDoc on the helper.","Validate the value shape at the API boundary with a schema (zod/joi).","Never accept a bare id from user input for composite-key entities."],"tags":["typeorm","relation-query-builder","composite-key","join-columns"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}