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

  1. Add a non-empty 'columns' array whose entries are Phalcon\Db\Column objects (each needs at least a 'type' constant).
  2. If the key exists under another name, rename it to exactly the lowercase string 'columns'.
  3. 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

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


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/5f414387b09324b4. Report an issue: GitHub.