{"id":"2c3a419848fb54c6","repo":"drizzle-team/drizzle-orm","slug":"arraycontains-requires-at-least-one-value","errorCode":null,"errorMessage":"arrayContains requires at least one value","messagePattern":"arrayContains requires at least one value","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/sql/expressions/conditions.ts","lineNumber":638,"sourceCode":"export function arrayContains<T>(\n\tcolumn: SQL.Aliased<T>,\n\tvalues: (T | Placeholder) | SQLWrapper,\n): SQL;\nexport function arrayContains<TColumn extends Column>(\n\tcolumn: TColumn,\n\tvalues: (GetColumnData<TColumn, 'raw'> | Placeholder) | SQLWrapper,\n): SQL;\nexport function arrayContains<T extends SQLWrapper>(\n\tcolumn: Exclude<T, SQL.Aliased | Column>,\n\tvalues: (unknown | Placeholder)[] | SQLWrapper,\n): SQL;\nexport function arrayContains(\n\tcolumn: SQLWrapper,\n\tvalues: (unknown | Placeholder)[] | SQLWrapper,\n): SQL {\n\tif (Array.isArray(values)) {\n\t\tif (values.length === 0) {\n\t\t\tthrow new Error('arrayContains requires at least one value');\n\t\t}\n\t\tconst array = sql`${bindIfParam(values, column)}`;\n\t\treturn sql`${column} @> ${array}`;\n\t}\n\n\treturn sql`${column} @> ${bindIfParam(values, column)}`;\n}\n\n/**\n * Test that the list passed as the second argument contains\n * all elements of a column or expression.\n *\n * ## Throws\n *\n * The argument passed in the second array can't be empty:\n * if an empty is provided, this method will throw.\n *\n * ## Examples","sourceCodeStart":620,"sourceCodeEnd":656,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/sql/expressions/conditions.ts#L620-L656","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst rows = await db.select().from(posts)\n  .where(arrayContains(posts.tags, selectedTags)); // throws if selectedTags === []\n\n// after\nconst qb = db.select().from(posts);\nif (selectedTags.length > 0) {\n  qb.where(arrayContains(posts.tags, selectedTags));\n}\nconst rows = await qb;","handlingStrategy":"validation","validationCode":"function safeArrayContains(column, values) {\n  if (Array.isArray(values) && values.length === 0) {\n    return undefined; // caller skips the predicate\n  }\n  return arrayContains(column, values);\n}","typeGuard":"const isNonEmptyArray = (v): v is unknown[] => Array.isArray(v) && v.length > 0;","tryCatchPattern":null,"preventionTips":["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."],"tags":["validation","postgres-array","query-builder"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}