laravel/framework · error · InvalidArgumentException
The returning columns must not be empty.
Error message
The returning columns must not be empty.
What it means
Thrown by insertOrIgnoreReturning when $returning is an empty array `[]`. The default value is ['*'], but if a caller explicitly passes [] the method has nothing to RETURN (Postgres RETURNING clause requires at least one column), so it aborts. Returning columns are how the caller learns which rows were actually inserted versus ignored.
Source
Thrown at src/Illuminate/Database/Query/Builder.php:4217
/**
* Insert new records into the database and returning specified columns with optional ignoring specific conflicts.
*
* @param non-empty-array<non-empty-string> $returning
* @param non-empty-string|non-empty-array<non-empty-string>|null $uniqueBy
* @return \Illuminate\Support\Collection
*/
public function insertOrIgnoreReturning(array $values, array $returning = ['*'], array|string|null $uniqueBy = null)
{
if (empty($values)) {
return new Collection;
}
if ($uniqueBy === [] || $uniqueBy === '') {
throw new InvalidArgumentException('The unique columns must not be empty.');
}
if ($returning === []) {
throw new InvalidArgumentException('The returning columns must not be empty.');
}
if (! is_array(array_first($values))) {
$values = [$values];
} else {
foreach ($values as $key => $value) {
ksort($value);
$values[$key] = $value;
}
}
$this->applyBeforeQueryCallbacks();
$sql = $this->grammar->compileInsertOrIgnoreReturning($this, $values, $returning, $uniqueBy === null ? null : Arr::wrap($uniqueBy));
$result = new Collection(
$this->connection->selectFromWriteConnection($sql, $this->cleanBindings(Arr::flatten($values, 1)))View on GitHub (pinned to bd6b5437e6)
Solutions
- Pass `['*']` to return all columns: `insertOrIgnoreReturning($values, ['*'], $uniqueBy)`.
- Pass at least one real column: `['id']` is usually sufficient to identify inserted rows.
- Validate the allowlist result: `if (!$cols) $cols = ['id'];`.
- If you genuinely do not need returned rows, use `insertOrIgnore()` instead.
Example fix
// before
$rows = DB::table('users')->insertOrIgnoreReturning($values, [], 'email');
// => The returning columns must not be empty.
// after
$rows = DB::table('users')->insertOrIgnoreReturning($values, ['id','email'], 'email'); Defensive patterns
Strategy: validation
Validate before calling
if ($returning === []) {
$returning = ['*'];
}
$table->insertOrIgnoreReturning($values, $returning, $uniqueBy); Type guard
/** @param non-empty-array<non-empty-string> $r */
function isValidReturning(array $r): bool
{
return $r !== [] && array_all($r, fn($v) => is_string($v) && $v !== '');
} Try / catch
// Validate the returning list before the call. Use insertOrIgnore() if no return rows are needed.
Prevention
- Default $returning to ['*'] or ['id'] in repository methods.
- Validate allowlist filters so they never reduce to an empty list.
- Document the non-empty requirement in the helper's docblock.
When it happens
Trigger: Calling `insertOrIgnoreReturning($values, [])`. Building $returning from `array_intersect($allCols, $allowedCols)` when $allowedCols yields no matches. Copy-paste from insert() (which has no returning param) leaving an empty array literal.
Common situations: Allowlist filtering that produces an empty set; column-permission layers stripping all columns; refactoring where the returning list was optional but the signature now requires it.
Related errors
- The unique columns must not be empty.
- A subquery must be a query builder instance, a Closure, or a
- Nested arrays may not be passed to whereIn method.
- The number of columns must match the number of values
- Order direction must be a SortDirection, "asc" or "desc".
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/0b49c6adb21acea4.json.
Report an issue: GitHub.