phalcon/cphalcon · error · ReturningRequiresColumn
RETURNING requires at least one column or '*'
Error message
RETURNING requires at least one column or '*'
What it means
The PostgreSQL dialect's returning() helper appends a RETURNING clause to an INSERT/UPDATE/DELETE and throws ReturningRequiresColumn when the columns array is empty. RETURNING with no column list is not valid PostgreSQL (there is no bare 'RETURNING' without a projection), so the helper demands at least one column name or the literal '*' as the single element.
Source
Thrown at phalcon/Db/Dialect/Postgresql.zep:910
if column->hasDefault() {
let defaultValue = this->castDefault(column);
let sql .= sqlAlterTable . " ALTER COLUMN \"" . column->getName() . "\" SET DEFAULT " . defaultValue;
}
}
return sql;
}
/**
* Appends a `RETURNING` clause to the supplied INSERT/UPDATE/DELETE
* statement. Pass `["*"]` for `RETURNING *`, or a list of column names.
*/
public function returning( string sqlQuery, array columns) -> string
{
var first;
if unlikely empty columns {
throw new ReturningRequiresColumn();
}
if count(columns) == 1 {
let first = (string) columns[0];
if first == "*" {
return sqlQuery . " RETURNING *";
}
}
return sqlQuery . " RETURNING " . this->getColumnList(columns);
}
/**
* PostgreSQL supports materialized views (`CREATE MATERIALIZED VIEW`).
*/
public function supportsMaterializedViews() -> bool
{View on GitHub (pinned to b7419de9cd)
Solutions
- Pass a non-empty list: returning($sql, ['*']) for all columns, or returning($sql, ['id', 'created_at'])
- Skip the RETURNING clause entirely when you do not need returned columns instead of calling with an empty array
- Default the list: $columns = $columns ?: ['*'] before the call
Example fix
// before $sql = $dialect->returning($insertSql, []); // after $sql = $dialect->returning($insertSql, ['*']);
Defensive patterns
Strategy: validation
Validate before calling
if (empty($columns)) {
throw new InvalidArgumentException('RETURNING requires at least one column or "*"');
}
// or default: $columns = $columns ?: ['*']; Type guard
function isNonEmptyColumnList(array $columns): bool
{
return $columns !== [] && array_reduce($columns, fn($ok, $c) => $ok && is_string($c) && $c !== '', true);
} Try / catch
try {
$sql = $dialect->returning($sql, $columns);
} catch (\Phalcon\Db\Exceptions\ReturningRequiresColumn $e) {
$sql = $dialect->returning($sql, ['*']); // or skip RETURNING
} Prevention
- Default the RETURNING list to ['*'] in your DAO helper
- Skip the RETURNING call when no columns are requested rather than passing []
- Beware array_filter(): it can leave an empty list that was non-empty before
When it happens
Trigger: Calling $dialect->returning($sql, []) or returning($sql, array_filter($cols)) where the filter removed everything; building the column list from a variable that is null/empty, e.g. when no auto-generated columns were requested.
Common situations: Generic DAO layers that add RETURNING only when generated columns are configured and pass the empty list anyway; refactors that changed the default from ['*'] to []; request-driven column lists that arrive empty.
Related errors
- The index 'columns' is required in the definition array
- The index 'sql' is required in the definition array
- Unrecognized PostgreSQL data type at column {}
- The table must contain at least one column
- Unable to insert into {table} without data
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/ebd36590dd3036ad.
Report an issue: GitHub.