{"id":"2ddee9c318186bf4","repo":"drizzle-team/drizzle-orm","slug":"values-must-be-called-with-at-least-one-value-2ddee9","errorCode":null,"errorMessage":"values() must be called with at least one value","messagePattern":"values\\(\\) must be called with at least one value","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/singlestore-core/query-builders/insert.ts","lineNumber":68,"sourceCode":"\tconstructor(\n\t\tprivate table: TTable,\n\t\tprivate session: SingleStoreSession,\n\t\tprivate dialect: SingleStoreDialect,\n\t) {}\n\n\tignore(): this {\n\t\tthis.shouldIgnore = true;\n\t\treturn this;\n\t}\n\n\tvalues(value: SingleStoreInsertValue<TTable>): SingleStoreInsertBase<TTable, TQueryResult, TPreparedQueryHKT>;\n\tvalues(values: SingleStoreInsertValue<TTable>[]): SingleStoreInsertBase<TTable, TQueryResult, TPreparedQueryHKT>;\n\tvalues(\n\t\tvalues: SingleStoreInsertValue<TTable> | SingleStoreInsertValue<TTable>[],\n\t): SingleStoreInsertBase<TTable, TQueryResult, TPreparedQueryHKT> {\n\t\tvalues = Array.isArray(values) ? values : [values];\n\t\tif (values.length === 0) {\n\t\t\tthrow new Error('values() must be called with at least one value');\n\t\t}\n\t\tconst mappedValues = values.map((entry) => {\n\t\t\tconst result: Record<string, Param | SQL> = {};\n\t\t\tconst cols = this.table[Table.Symbol.Columns];\n\t\t\tfor (const colKey of Object.keys(entry)) {\n\t\t\t\tconst colValue = entry[colKey as keyof typeof entry];\n\t\t\t\tresult[colKey] = is(colValue, SQL) ? colValue : new Param(colValue, cols[colKey]);\n\t\t\t}\n\t\t\treturn result;\n\t\t});\n\n\t\treturn new SingleStoreInsertBase(this.table, mappedValues, this.shouldIgnore, this.session, this.dialect);\n\t}\n}\n\nexport type SingleStoreInsertWithout<\n\tT extends AnySingleStoreInsert,\n\tTDynamic extends boolean,","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/singlestore-core/query-builders/insert.ts#L50-L86","documentation":"Thrown in SingleStoreInsertBuilder.values (insert.ts:68) when the normalized values array has length 0. An INSERT with zero value rows is not valid SQL, so Drizzle rejects it at the builder level rather than emitting an incomplete statement.","triggerScenarios":"Calling db.insert(table).values([]) directly; passing a runtime array variable that happens to be empty (e.g. results of a filter that returned nothing); spreading a generated list without a guard.","commonSituations":"Batch insert paths where upstream filtering produced no rows; UI bulk-save with no changes; ETL step that receives an empty chunk; tests that pass [] as a placeholder.","solutions":["Guard the insert: `if (rows.length) await db.insert(t).values(rows);`.","Default to a no-op or skip when the input array is empty.","Validate at the API boundary that the payload contains at least one record."],"exampleFix":"// before\nawait db.insert(users).values(batch);\n// after\nif (batch.length > 0) {\n  await db.insert(users).values(batch);\n}","handlingStrategy":"validation","validationCode":"if (Array.isArray(rows) ? rows.length === 0 : false) {\n  throw new Error('Cannot insert an empty batch');\n}\nif (rows.length > 0) await db.insert(table).values(rows);","typeGuard":"function hasAtLeastOneValue(v) { return Array.isArray(v) ? v.length > 0 : v != null; }","tryCatchPattern":null,"preventionTips":["Guard batch inserts with `if (rows.length)`.","Validate API payloads contain at least one record before inserting.","Treat empty batches as a no-op, not an error path."],"tags":["insert","validation","singlestore","batch"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}