{"id":"014c7392f5a2e88f","repo":"drizzle-team/drizzle-orm","slug":"set-operator-error-union-intersect-except-s-014c73","errorCode":null,"errorMessage":"Set operator error (union / intersect / except): selected fields are not the same or are in a different order","messagePattern":"Set operator error \\(union / intersect / except\\): selected fields are not the same or are in a different order","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/pg-core/query-builders/select.ts","lineNumber":523,"sourceCode":"\t\trightSelection:\n\t\t\t| ((setOperators: GetPgSetOperators) => SetOperatorRightSelect<TValue, TResult>)\n\t\t\t| SetOperatorRightSelect<TValue, TResult>,\n\t) => PgSelectWithout<\n\t\tthis,\n\t\tTDynamic,\n\t\tPgSetOperatorExcludedMethods,\n\t\ttrue\n\t> {\n\t\treturn (rightSelection) => {\n\t\t\tconst rightSelect = (typeof rightSelection === 'function'\n\t\t\t\t? rightSelection(getPgSetOperators())\n\t\t\t\t: rightSelection) as TypedQueryBuilder<\n\t\t\t\t\tany,\n\t\t\t\t\tTResult\n\t\t\t\t>;\n\n\t\t\tif (!haveSameKeys(this.getSelectedFields(), rightSelect.getSelectedFields())) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'Set operator error (union / intersect / except): selected fields are not the same or are in a different order',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.config.setOperators.push({ type, isAll, rightSelect });\n\t\t\treturn this as any;\n\t\t};\n\t}\n\n\t/**\n\t * Adds `union` set operator to the query.\n\t *\n\t * Calling this method will combine the result sets of the `select` statements and remove any duplicate rows that appear across them.\n\t *\n\t * See docs: {@link https://orm.drizzle.team/docs/set-operations#union}\n\t *\n\t * @example\n\t *","sourceCodeStart":505,"sourceCodeEnd":541,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/pg-core/query-builders/select.ts#L505-L541","documentation":"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.","triggerScenarios":"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}`.","commonSituations":"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.","solutions":["Align both selects to the same field keys in the same order.","Project both sides through a common object shape: select({ id, name }) on every branch.","Use sql aliases consistently so the keys match exactly.","After adding a column to one branch, add the corresponding field to all branches."],"exampleFix":"// before\ndb.select({ id: t1.id }).from(t1)\n  .union(db.select({ id: t2.id, name: t2.name }).from(t2)); // mismatch\n\n// after\ndb.select({ id: t1.id, name: t1.name }).from(t1)\n  .union(db.select({ id: t2.id, name: t2.name }).from(t2));","handlingStrategy":"validation","validationCode":"import { haveSameKeys } from 'drizzle-orm/utils'; // or local copy\n\nfunction assertUnionCompatible(left: any, right: any) {\n  const l = left.getSelectedFields();\n  const r = right.getSelectedFields();\n  if (!sameKeys(l, r)) {\n    throw new Error(`union mismatch: ${Object.keys(l)} vs ${Object.keys(r)}`);\n  }\n}\nfunction sameKeys(a: Record<string, unknown>, b: Record<string, unknown>) {\n  const ak = Object.keys(a), bk = Object.keys(b);\n  return ak.length === bk.length && ak.every((k, i) => k === bk[i]);\n}","typeGuard":"function fieldsMatch(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\n  const ak = Object.keys(a), bk = Object.keys(b);\n  return ak.length === bk.length && ak.every((k, i) => k === bk[i]);\n}","tryCatchPattern":null,"preventionTips":["Project all union branches through a shared selector object.","Update every branch in lockstep when adding a field.","Keep alias keys identical across branches."],"tags":["select","set-operators","union","validation"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}