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 in createSetOperator (select.ts:502) for the method-chained form (.union/.unionAll/.intersect/.except/.minus). Before pushing the operator it compares the keys of the left and right selections via haveSameKeys; SQL set operators require both sides to project identical columns in the same order, so a mismatch is rejected at build time.

Source

Thrown at drizzle-orm/src/singlestore-core/query-builders/select.ts:502

		rightSelection:
			| ((setOperators: GetSingleStoreSetOperators) => SetOperatorRightSelect<TValue, TResult>)
			| SetOperatorRightSelect<TValue, TResult>,
	) => SingleStoreSelectWithout<
		this,
		TDynamic,
		SingleStoreSetOperatorExcludedMethods,
		true
	> {
		return (rightSelection) => {
			const rightSelect = (typeof rightSelection === 'function'
				? rightSelection(getSingleStoreSetOperators())
				: 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. Align both selects to the exact same set of keys in the same order, ideally by projecting explicit aliases.
  2. Use sql`...` aliases to normalize differing source columns to a common output key.
  3. Extract the shared selection shape into a constant and reuse it on both sides.

Example fix

// before
await db.select({ id: users.id }).from(users)
  .union(db.select({ name: customers.name }).from(customers));
// after
await db.select({ label: users.id }).from(users)
  .union(db.select({ label: customers.name }).from(customers));
Defensive patterns

Strategy: validation

Validate before calling

import { haveSameKeys } from 'drizzle-orm/utils';
// both args are select builders
function assertSameSelectionKeys(left, right) {
  if (!haveSameKeys(left.getSelectedFields(), right.getSelectedFields())) {
    throw new Error('Union branches must select the same keys in the same order');
  }
}

Type guard

function sameSelectionShape(left, right) {
  return haveSameKeys(left.getSelectedFields(), right.getSelectedFields());
}

Prevention

When it happens

Trigger: Calling qb.union(otherQb) where qb selects {a, b} and otherQb selects {a, c} or selects the same columns in a different key order; selecting computed/aliased fields whose keys differ between branches.

Common situations: Refactoring one side of a union and changing its select shape; combining selects from tables with different column subsets expecting them to align; ordering object keys differently across two builders.

Related errors


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