{"id":"64c1c38475ee474d","repo":"drizzle-team/drizzle-orm","slug":"set-operator-error-union-intersect-except-s-64c1c3","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":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/sqlite-core/query-builders/select.ts","lineNumber":455,"sourceCode":"\t\trightSelection:\n\t\t\t| ((setOperators: GetSQLiteSetOperators) => SetOperatorRightSelect<TValue, TResult>)\n\t\t\t| SetOperatorRightSelect<TValue, TResult>,\n\t) => SQLiteSelectWithout<\n\t\tthis,\n\t\tTDynamic,\n\t\tSQLiteSetOperatorExcludedMethods,\n\t\ttrue\n\t> {\n\t\treturn (rightSelection) => {\n\t\t\tconst rightSelect = (typeof rightSelection === 'function'\n\t\t\t\t? rightSelection(getSQLiteSetOperators())\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":437,"sourceCodeEnd":473,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/sqlite-core/query-builders/select.ts#L437-L473","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make both selects project exactly the same keys in the same order.","If column types differ, alias and cast so the key sets align (e.g. both expose {id, label}).","Use a shared selection-config object/type for both halves to prevent drift."],"exampleFix":"// before\ndb.select({ id: users.id, label: users.name }).from(users)\n  .union(db.select({ id: posts.id, label2: posts.title }).from(posts)); // 'label' vs 'label2' -> throws\n\n// after\ndb.select({ id: users.id, label: users.name }).from(users)\n  .union(db.select({ id: posts.id, label: posts.title }).from(posts));","handlingStrategy":"type-guard","validationCode":"function assertSameSelection(left, right) {\n  const lk = Object.keys(left), rk = Object.keys(right);\n  if (lk.length !== rk.length || lk.some((k, i) => k !== rk[i])) {\n    throw new Error('Set-operator branches must share the same selected keys/order');\n  }\n}","typeGuard":"type SelectionOf<T> = { [K in keyof T]: T[K] };\nfunction sameSelectionShape<L, R>(l: SelectionOf<L>, r: SelectionOf<R>): boolean {\n  const lk = Object.keys(l), rk = Object.keys(r);\n  return lk.length === rk.length && lk.every((k, i) => k === rk[i]);\n}","tryCatchPattern":null,"preventionTips":["Share a single selection-config object across all union branches.","Annotate each branch's .select() with the same type to catch drift at compile time.","After editing one branch, update the others to keep keys/order aligned."],"tags":["set-operators","union","select","schema-match"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}