drizzle-team/drizzle-orm · error · Error

arrayContained requires at least one value

Error message

arrayContained requires at least one value

What it means

Thrown by arrayContained() when the values argument is an empty Array. arrayContained builds a '<@' (contained-by) operator expression, which has no defined meaning against an empty list, so drizzle refuses to generate it (conditions.ts:685-686). A non-array second argument (SQLWrapper or scalar) skips the check.

Source

Thrown at drizzle-orm/src/sql/expressions/conditions.ts:686

export function arrayContained<T>(
	column: SQL.Aliased<T>,
	values: (T | Placeholder) | SQLWrapper,
): SQL;
export function arrayContained<TColumn extends Column>(
	column: TColumn,
	values: (GetColumnData<TColumn, 'raw'> | Placeholder) | SQLWrapper,
): SQL;
export function arrayContained<T extends SQLWrapper>(
	column: Exclude<T, SQL.Aliased | Column>,
	values: (unknown | Placeholder)[] | SQLWrapper,
): SQL;
export function arrayContained(
	column: SQLWrapper,
	values: (unknown | Placeholder)[] | SQLWrapper,
): SQL {
	if (Array.isArray(values)) {
		if (values.length === 0) {
			throw new Error('arrayContained requires at least one value');
		}
		const array = sql`${bindIfParam(values, column)}`;
		return sql`${column} <@ ${array}`;
	}

	return sql`${column} <@ ${bindIfParam(values, column)}`;
}

/**
 * Test that a column or expression contains any elements of
 * the list passed as the second argument.
 *
 * ## Throws
 *
 * The argument passed in the second array can't be empty:
 * if an empty is provided, this method will throw.
 *
 * ## Examples

View on GitHub (pinned to b7862528fd)

Solutions

  1. Conditionally apply the predicate only when the array is non-empty.
  2. Treat empty input as 'match all' and skip the where clause.
  3. Coalesce the array to a sentinel value that always satisfies the intended semantics.

Example fix

// before
.where(arrayContained(posts.tags, filterTags)) // filterTags === [] throws

// after
if (filterTags.length > 0) {
  query.where(arrayContained(posts.tags, filterTags));
}
Defensive patterns

Strategy: validation

Validate before calling

function safeArrayContained(column, values) {
  if (Array.isArray(values) && values.length === 0) return undefined;
  return arrayContained(column, values);
}

Type guard

const isNonEmptyArray = (v): v is unknown[] => Array.isArray(v) && v.length > 0;

Prevention

When it happens

Trigger: Calling arrayContained(column, []); passing an array-typed filter variable that has been emptied at runtime; arrayContained(posts.tags, userSelectedTags) with userSelectedTags === [].

Common situations: Building a dynamic 'subset of' filter from a multi-select form field where the user cleared all selections; defaulting an optional filter to [] and forwarding it unconditionally; migrating from a raw SQL fragment that tolerated empty arrays.

Related errors


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