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 the method-form set operator (.union/.intersect/.except on a select builder, select.ts:455) when the left and right selects do not expose the same selected-field keys in the same order (checked via order-sensitive haveSameKeys). SQL set operators require column-compatible result sets, so drizzle validates structurally before emitting the query.

Source

Thrown at drizzle-orm/src/sqlite-core/query-builders/select.ts:455

		rightSelection:
			| ((setOperators: GetSQLiteSetOperators) => SetOperatorRightSelect<TValue, TResult>)
			| SetOperatorRightSelect<TValue, TResult>,
	) => SQLiteSelectWithout<
		this,
		TDynamic,
		SQLiteSetOperatorExcludedMethods,
		true
	> {
		return (rightSelection) => {
			const rightSelect = (typeof rightSelection === 'function'
				? rightSelection(getSQLiteSetOperators())
				: 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 exactly the same keys in the same order.
  2. If column types differ, alias and cast so the key sets align (e.g. both expose {id, label}).
  3. Use a shared selection-config object/type for both halves to prevent drift.

Example fix

// before
db.select({ id: users.id, label: users.name }).from(users)
  .union(db.select({ id: posts.id, label2: posts.title }).from(posts)); // 'label' vs 'label2' -> throws

// after
db.select({ id: users.id, label: users.name }).from(users)
  .union(db.select({ id: posts.id, label: posts.title }).from(posts));
Defensive patterns

Strategy: type-guard

Validate before calling

function assertSameSelection(left, right) {
  const lk = Object.keys(left), rk = Object.keys(right);
  if (lk.length !== rk.length || lk.some((k, i) => k !== rk[i])) {
    throw new Error('Set-operator branches must share the same selected keys/order');
  }
}

Type guard

type SelectionOf<T> = { [K in keyof T]: T[K] };
function sameSelectionShape<L, R>(l: SelectionOf<L>, r: SelectionOf<R>): boolean {
  const lk = Object.keys(l), rk = Object.keys(r);
  return lk.length === rk.length && lk.every((k, i) => k === rk[i]);
}

Prevention

When it happens

Trigger: db.select({a: t1.a}).from(t1).union(db.select({b: t2.b}).from(t2)); selecting different columns, a different order, or a different count. Even identical column values under different keys fail because the comparison is on keys/order.

Common situations: Combining results from two tables with slightly different projections; adding a column to one side but not the other; reordering a select map during a refactor; using {a: true, b: true} on one side and {b: true, a: true} on the other.

Related errors


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