phalcon/cphalcon · error · TableMustHaveColumn
The table must contain at least one column
Error message
The table must contain at least one column
What it means
Phalcon\Db\Adapter\Pdo\Postgresql::createTable() requires the $definition array to contain a 'columns' entry holding the Phalcon\Db\Column definitions for the new table. If the key cannot be fetched at all, the adapter throws TableMustHaveColumn before any SQL is generated. PostgreSQL cannot create a table without a column list, so the adapter rejects the definition up front.
Source
Thrown at phalcon/Db/Adapter/Pdo/Postgresql.zep:108
parent::connect(descriptor);
if !empty schema {
let sql = "SET search_path TO '" . schema . "'";
this->execute(sql);
}
}
/**
* Creates a table
*/
public function createTable( string tableName, string schemaName, array definition) -> bool
{
var sql, queries, query, exception, columns;
if unlikely !fetch columns, definition["columns"] {
throw new TableMustHaveColumn();
}
if unlikely empty columns {
throw new TableMustHaveColumn();
}
let sql = this->dialect->createTable(tableName, schemaName, definition);
let queries = explode(";", sql);
if count(queries) > 1 {
try {
this->{"begin"}();
for query in queries {
if empty query {
continue;
}View on GitHub (pinned to b7419de9cd)
Solutions
- Add a non-empty 'columns' array whose entries are Phalcon\Db\Column objects (each needs at least a 'type' constant).
- If the key exists under another name, rename it to exactly the lowercase string 'columns'.
- When building definitions dynamically, initialize with 'columns' => [] and assert count($definition['columns']) > 0 before calling createTable().
Example fix
// before
$connection->createTable('users', 'public', [
'indexes' => [['columns' => ['id'], 'type' => 'PRIMARY']],
]); // throws TableMustHaveColumn
// after
use Phalcon\Db\Column;
$connection->createTable('users', 'public', [
'columns' => [
new Column('id', ['type' => Column::TYPE_INTEGER, 'primary' => true]),
],
'indexes' => [['columns' => ['id'], 'type' => 'PRIMARY']],
]); Defensive patterns
Strategy: validation
Validate before calling
if (!isset($definition['columns']) || !is_array($definition['columns'])) {
throw new InvalidArgumentException('createTable definition requires a "columns" array');
}
$connection->createTable('users', 'public', $definition); Type guard
function hasCreateTableColumns(array $definition): bool
{
return isset($definition['columns'])
&& is_array($definition['columns'])
&& $definition['columns'] !== [];
} Prevention
- Start every table definition from a skeleton with 'columns' => [].
- Centralize definition building in one schema factory so the key is never hand-typed.
- Unit-test definition builders to always return a non-empty columns list.
When it happens
Trigger: Calling $connection->createTable('users', 'public', $definition) where $definition has no 'columns' key - e.g. it only carries 'indexes' or 'references', the key is typo'd ('cols', 'fields', 'column', wrong case), or the array was assembled dynamically and the columns entry was never set.
Common situations: Migration code assembling definitions from config or model metadata and skipping the columns entry; copy-pasting a MySQL example with a different shape; key-name typos; refactors that move the column list into a variable that ends up unset.
Related errors
- The index 'columns' is required in the definition array
- CHECK expression is required
- Column type is required
- Column type does not support scale parameter
- ON CONFLICT requires at least one conflict-target column
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/5f414387b09324b4.
Report an issue: GitHub.