drizzle-team/drizzle-orm · error · Error

Set operator error (union / intersect / except): selected fi

Error message

Set operator error (union / intersect / except): selected fields are not the same or are in a different order

What it means

Thrown by createSetOperator on the select builder (line 570) when a chained set operator (union/unionAll/intersect/intersectAll/except/exceptAll) is added and the right select's fields don't match the left select's fields (keys + order via haveSameKeys). Set operations require both sides to project the same shape.

Source

Thrown at drizzle-orm/src/mysql-core/query-builders/select.ts:570

		rightSelection:
			| ((setOperators: GetMySqlSetOperators) => SetOperatorRightSelect<TValue, TResult>)
			| SetOperatorRightSelect<TValue, TResult>,
	) => MySqlSelectWithout<
		this,
		TDynamic,
		MySqlSetOperatorExcludedMethods,
		true
	> {
		return (rightSelection) => {
			const rightSelect = (typeof rightSelection === 'function'
				? rightSelection(getMySqlSetOperators())
				: rightSelection) as TypedQueryBuilder<
					any,
					TResult
				>;

			if (!haveSameKeys(this.getSelectedFields(), rightSelect.getSelectedFields())) {
				throw new Error(
					'Set operator error (union / intersect / except): selected fields are not the same or are in a different order',
				);
			}

			this.config.setOperators.push({ type, isAll, rightSelect });
			return this as any;
		};
	}

	/**
	 * Adds `union` set operator to the query.
	 *
	 * Calling this method will combine the result sets of the `select` statements and remove any duplicate rows that appear across them.
	 *
	 * See docs: {@link https://orm.drizzle.team/docs/set-operations#union}
	 *
	 * @example
	 *

View on GitHub (pinned to b7862528fd)

Solutions

  1. Make both selects project identical keys in the same order.
  2. Alias fields on both sides so the key sets match exactly.
  3. If you need different shapes, combine them with a different query strategy (e.g. client-side merge).
  4. Double-check that aliased columns use the same alias key on both sides.

Example fix

// before
db.select({ id: users.id, name: users.name }).from(users)
  .union(db.select({ id: customers.id, email: customers.email }).from(customers));
// keys {id,name} vs {id,email} => throws

// after - align shapes
db.select({ id: users.id, label: users.name }).from(users)
  .union(db.select({ id: customers.id, label: customers.email }).from(customers));
Defensive patterns

Strategy: validation

Validate before calling

import { haveSameKeys } from '~/utils.ts';
if (!haveSameKeys(left.getSelectedFields(), right.getSelectedFields())) {
  throw new Error('Set-operator sides must select the same keys in the same order');
}

Type guard

function shapesMatch(a: { getSelectedFields(): Record<string, unknown> }, b: { getSelectedFields(): Record<string, unknown> }): boolean {
  return haveSameKeys(a.getSelectedFields(), b.getSelectedFields());
}

Prevention

When it happens

Trigger: db.select({ a, b }).from(t1).union(db.select({ a, c }).from(t2)) - different keys or order. The method-style operator validates against this.getSelectedFields() vs rightSelect.getSelectedFields().

Common situations: Different columns selected on each side; same columns in different order; one side aliased differently; refactored one select but not the other.

Related errors


AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03). Data as JSON: /data/errors/c9224c11b9d4a032.json. Report an issue: GitHub.