drizzle-team/drizzle-orm · error · Error
arrayContains requires at least one value
Error message
arrayContains requires at least one value
What it means
Thrown by arrayContains() when the second argument is an Array with zero elements. The function builds a PostgreSQL '@>' (array-contains-all) comparison, which is semantically meaningless with an empty set, so drizzle rejects it eagerly rather than emit SQL the database would reject or misinterpret. The guard is an explicit length check at conditions.ts:637-638.
Source
Thrown at drizzle-orm/src/sql/expressions/conditions.ts:638
export function arrayContains<T>(
column: SQL.Aliased<T>,
values: (T | Placeholder) | SQLWrapper,
): SQL;
export function arrayContains<TColumn extends Column>(
column: TColumn,
values: (GetColumnData<TColumn, 'raw'> | Placeholder) | SQLWrapper,
): SQL;
export function arrayContains<T extends SQLWrapper>(
column: Exclude<T, SQL.Aliased | Column>,
values: (unknown | Placeholder)[] | SQLWrapper,
): SQL;
export function arrayContains(
column: SQLWrapper,
values: (unknown | Placeholder)[] | SQLWrapper,
): SQL {
if (Array.isArray(values)) {
if (values.length === 0) {
throw new Error('arrayContains requires at least one value');
}
const array = sql`${bindIfParam(values, column)}`;
return sql`${column} @> ${array}`;
}
return sql`${column} @> ${bindIfParam(values, column)}`;
}
/**
* Test that the list passed as the second argument contains
* all elements of a column or expression.
*
* ## Throws
*
* The argument passed in the second array can't be empty:
* if an empty is provided, this method will throw.
*
* ## ExamplesView on GitHub (pinned to b7862528fd)
Solutions
- Guard the caller: if (values.length) ... else skip the predicate or fall back to a safe default.
- Provide a meaningful fallback array (e.g. a sentinel) when the source list is empty.
- If 'no filter' is the intent, omit the .where(arrayContains(...)) clause entirely when values is empty.
Example fix
// before
const rows = await db.select().from(posts)
.where(arrayContains(posts.tags, selectedTags)); // throws if selectedTags === []
// after
const qb = db.select().from(posts);
if (selectedTags.length > 0) {
qb.where(arrayContains(posts.tags, selectedTags));
}
const rows = await qb; Defensive patterns
Strategy: validation
Validate before calling
function safeArrayContains(column, values) {
if (Array.isArray(values) && values.length === 0) {
return undefined; // caller skips the predicate
}
return arrayContains(column, values);
} Type guard
const isNonEmptyArray = (v): v is unknown[] => Array.isArray(v) && v.length > 0;
Prevention
- Never forward a user-controlled filter array straight into arrayContains without a length check.
- Centralise a 'where' builder that silently drops empty-array predicates.
- Treat an empty filter as 'no constraint' rather than an empty SQL array.
When it happens
Trigger: Calling arrayContains(column, []) or passing a runtime-computed array that resolved to [], e.g. arrayContains(posts.tags, selectedTags) where selectedTags is filtered to nothing. Passing a non-array (SQLWrapper/Placeholder) never triggers it — only an empty literal/variable Array does.
Common situations: Filtering by a tags/categories array that the user deselected entirely in the UI; a search filter that produced zero selections; passing an empty default constant by mistake. Happens most often in dynamic query builders where the values list is assembled from user input.
Related errors
- arrayContained requires at least one value
- arrayOverlaps requires at least one value
- values() must be called with at least one value
- Cannot pass undefined values to any set operator
- You have an empty array for "${name}" enum values
AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03).
Data as JSON: /data/errors/2c3a419848fb54c6.json.
Report an issue: GitHub.