n8n-io/n8n · error · TypeORMError

You cannot update relations of multiple entities with the sa

Error message

You cannot update relations of multiple entities with the same related object. Provide a single entity into .of method.

What it means

In RelationUpdater.update for isOneToOneNotOwner || isOneToMany branches, TypeORM throws TypeORMError if this.expressionMap.of is an array. The inverse-side update strategy writes the parent's FK value into the related rows; applying the same value to multiple parents is ambiguous, so a single parent is required.

Source

Thrown at packages/@n8n/typeorm/src/query-builder/RelationUpdater.ts:87

					parameters[parameterName] = ObjectUtils.isObject(of)
						? column.referencedColumn!.getEntityValue(of)
						: of;
					conditions.push(`${column.propertyPath} = :${parameterName}`);
				});
			});
			const condition = conditions.map((str) => '(' + str + ')').join(' OR ');
			if (!condition) return;

			await this.queryBuilder
				.createQueryBuilder()
				.update(relation.inverseEntityMetadata.target)
				.set(updateSet)
				.where(condition)
				.setParameters(parameters)
				.execute();
		} else if (relation.isOneToOneNotOwner || relation.isOneToMany) {
			if (Array.isArray(this.expressionMap.of))
				throw new TypeORMError(
					`You cannot update relations of multiple entities with the same related object. Provide a single entity into .of method.`,
				);

			const of = this.expressionMap.of;
			const updateSet = relation.inverseRelation!.joinColumns.reduce((updateSet, joinColumn) => {
				const relationValue = ObjectUtils.isObject(of)
					? joinColumn.referencedColumn!.getEntityValue(of)
					: of;
				joinColumn.setEntityValue(updateSet, relationValue);
				return updateSet;
			}, {} as any);

			if (!value || (Array.isArray(value) && !value.length)) return;

			await this.queryBuilder
				.createQueryBuilder()
				.update(relation.inverseEntityMetadata.target)
				.set(updateSet)

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Loop and call per-parent: for (const u of users) await qb.relation(User,'photos').of(u).add(photo).
  2. Restructure as a direct update on the inverse entity with an In(...) condition when bulk is required.
  3. Validate that .of receives a single object before constructing the relation call.

Example fix

// before
await qb.relation(User,'photos').of(users).set(photo); // users is an array
// after
for (const u of users) await qb.relation(User,'photos').of(u).set(photo);
Defensive patterns

Strategy: validation

Validate before calling

function requireSingleOf(qb: any, parent: unknown) {
  if (Array.isArray(parent)) throw new Error('One-to-many/inverse-one-to-one update requires a single parent in .of()');
  qb.of(parent);
}

Type guard

function isSingleParent(value: unknown): boolean { return !Array.isArray(value) && value != null; }

Prevention

When it happens

Trigger: qb.relation(User,'photos').of([user1, user2]).set(photo) or .add(photo) — the parent side is plural for a one-to-many/inverse-one-to-one relation.

Common situations: Bulk helpers that pass arrays uniformly to all relation calls; refactoring a single-parent call into a loop but accidentally passing the array to .of.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/59de944b05e7f0b4. Report an issue: GitHub.