drizzle-team/drizzle-orm · error · Error
Cannot pass undefined values to any set operator
Error message
Cannot pass undefined values to any set operator
What it means
Thrown by SQLiteDialect.buildSetOperations (dialect.ts:445) when the setOperators array passed in has undefined/null as its first element. Because the array is destructured as [setOperator, ...rest], a leading undefined means the caller pushed a malformed entry — drizzle cannot build a UNION/INTERSECT/EXCEPT without a defined operator config.
Source
Thrown at drizzle-orm/src/sqlite-core/dialect.ts:445
const finalQuery =
sql`${withSql}select${distinctSql} ${selection} from ${tableSql}${joinsSql}${whereSql}${groupBySql}${havingSql}${orderBySql}${limitSql}${offsetSql}`;
if (setOperators.length > 0) {
return this.buildSetOperations(finalQuery, setOperators);
}
return finalQuery;
}
buildSetOperations(
leftSelect: SQL,
setOperators: SQLiteSelectConfig['setOperators'],
): SQL {
const [setOperator, ...rest] = setOperators;
if (!setOperator) {
throw new Error('Cannot pass undefined values to any set operator');
}
if (rest.length === 0) {
return this.buildSetOperationQuery({ leftSelect, setOperator });
}
// Some recursive magic here
return this.buildSetOperations(
this.buildSetOperationQuery({ leftSelect, setOperator }),
rest,
);
}
buildSetOperationQuery({
leftSelect,
setOperator: { type, isAll, rightSelect, limit, orderBy, offset },
}: {
leftSelect: SQL;View on GitHub (pinned to b7862528fd)
Solutions
- Filter undefined out of any dynamically built set-operator array before it reaches the query.
- Use the public .union()/.intersect()/.except() builder methods rather than constructing setOperators by hand.
- Assert each pushed entry is a defined object before appending.
Example fix
// before
const ops = branches.map((b) => b ? { type: 'union', isAll: false, rightSelect: b } : undefined);
// an undefined slipped into the array -> throws at build time
// after
const ops = branches
.filter((b): b is Select => b !== undefined)
.map((b) => ({ type: 'union', isAll: false, rightSelect: b })); Defensive patterns
Strategy: validation
Validate before calling
function cleanSetOperators(ops) {
return ops.filter((op) => op != null && op.type && op.rightSelect);
} Type guard
const isSetOperator = (o): o is { type: string; rightSelect: unknown } =>
o != null && typeof o.type === 'string' && !!o.rightSelect; Prevention
- Prefer the public .union()/.intersect()/.except() API over hand-built setOperators arrays.
- Always filter undefined out of dynamically assembled operator arrays.
- Type the array strictly so TS rejects undefined entries.
When it happens
Trigger: Programmatically building the setOperators array and accidentally pushing undefined; a union/intersect/except chain where one branch evaluated to undefined; an internal API misuse that left a hole in the setOperators list.
Common situations: Dynamic query assembly that conditionally appends set operators and pushes the result of a ternary that resolved to undefined; version-mismatch where the internal config shape changed; hand-constructed select config.
Related errors
- Set operator error (union / intersect / except): selected fi
- Set operator error (union / intersect / except): selected fi
- Cannot pass undefined values to any set operator
- Cannot pass undefined values to any set operator
- values() must be called with at least one value
AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03).
Data as JSON: /data/errors/1514153557a9f495.json.
Report an issue: GitHub.