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

The chainable set-operator helpers (select.ts:514) validate that both sides of a union/unionAll/intersect/intersectAll/except/exceptAll select the same fields in the same order via haveSameKeys. Postgres requires corresponding columns in set operations to match in number and compatible types positionally, so Drizzle enforces identical selected-field keys up front to fail fast instead of relying on the server.

Source

Thrown at drizzle-orm/src/pg-core/query-builders/select.ts:523

		rightSelection:
			| ((setOperators: GetPgSetOperators) => SetOperatorRightSelect<TValue, TResult>)
			| SetOperatorRightSelect<TValue, TResult>,
	) => PgSelectWithout<
		this,
		TDynamic,
		PgSetOperatorExcludedMethods,
		true
	> {
		return (rightSelection) => {
			const rightSelect = (typeof rightSelection === 'function'
				? rightSelection(getPgSetOperators())
				: 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 same field keys in the same order.
  2. Project both sides through a common object shape: select({ id, name }) on every branch.
  3. Use sql aliases consistently so the keys match exactly.
  4. After adding a column to one branch, add the corresponding field to all branches.

Example fix

// before
db.select({ id: t1.id }).from(t1)
  .union(db.select({ id: t2.id, name: t2.name }).from(t2)); // mismatch

// after
db.select({ id: t1.id, name: t1.name }).from(t1)
  .union(db.select({ id: t2.id, name: t2.name }).from(t2));
Defensive patterns

Strategy: validation

Validate before calling

import { haveSameKeys } from 'drizzle-orm/utils'; // or local copy

function assertUnionCompatible(left: any, right: any) {
  const l = left.getSelectedFields();
  const r = right.getSelectedFields();
  if (!sameKeys(l, r)) {
    throw new Error(`union mismatch: ${Object.keys(l)} vs ${Object.keys(r)}`);
  }
}
function sameKeys(a: Record<string, unknown>, b: Record<string, unknown>) {
  const ak = Object.keys(a), bk = Object.keys(b);
  return ak.length === bk.length && ak.every((k, i) => k === bk[i]);
}

Type guard

function fieldsMatch(a: Record<string, unknown>, b: Record<string, unknown>): boolean {
  const ak = Object.keys(a), bk = Object.keys(b);
  return ak.length === bk.length && ak.every((k, i) => k === bk[i]);
}

Prevention

When it happens

Trigger: db.select({a}).from(t1).union(db.select({b}).from(t2)) where the field keys/counts differ; selecting columns in a different order on each side; one side selecting `{a, b}` and the other `{a, b, c}`.

Common situations: Combining results from different tables; evolving one branch of a union and forgetting to update the other; selecting computed columns on one side but not the other; mismatched aliases in object selects.

Related errors


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