phalcon/cphalcon · error · MissingDefinitionKey

The index 'columns' is required in the definition array

Error message

The index 'columns' is required in the definition array

What it means

The PostgreSQL dialect's createTable() throws MissingDefinitionKey when the definition array passed to $adapter->createTable() lacks 'columns'. As with MySQL, at least one Phalcon\Db\Column is required before any 'indexes', 'references', or 'options' are processed; the check happens first thing in the method.

Source

Thrown at phalcon/Db/Dialect/Postgresql.zep:162

     */
    public function addPrimaryKey( string tableName,  string schemaName, <IndexInterface> index) -> string
    {
        return "ALTER TABLE " . this->prepareTable(tableName, schemaName) . " ADD CONSTRAINT \"" . tableName . "_PRIMARY\" PRIMARY KEY (" . this->getColumnList(index->getColumns()) . ")";
    }

    /**
     * Generates SQL to create a table
     */
    public function createTable( string tableName,  string schemaName,  array definition) -> string
    {
        var temporary, options, table, columns, column, indexes, index,
            reference, references, indexName, indexType, onDelete, onUpdate,
            columnDefinition, checks, check, tableComment;
        array createLines, primaryColumns;
        string indexSql, indexSqlAfterCreate, columnLine, referenceSql, sql;

        if unlikely !fetch columns, definition["columns"] {
            throw new MissingDefinitionKey("columns");
        }

        let table = this->prepareTable(tableName, schemaName);

        let temporary = false;
        if fetch options, definition["options"] {
            fetch temporary, options["temporary"];
            fetch tableComment, options["TABLE_COMMENT"];
        }

        /**
         * Create a temporary or normal table
         */
        if temporary {
            let sql = "CREATE TEMPORARY TABLE " . table . " (\n\t";
        } else {
            let sql = "CREATE TABLE " . table . " (\n\t";
        }

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Provide 'columns' as Column objects: $definition['columns'] = [new Column('id', ['type' => Column::TYPE_SERIAL, 'primary' => true]), ...]
  2. Skip createTable() when the computed columns list is empty
  3. Verify the source metadata/migration that generated the definition

Example fix

// before
$connection->createTable('robots', 'public', [
    'options' => ['TABLE_COMMENT' => 'robots'],
]);

// after
$connection->createTable('robots', 'public', [
    'columns' => [
        new Column('id', ['type' => Column::TYPE_SERIAL, 'primary' => true]),
        new Column('name', ['type' => Column::TYPE_VARCHAR, 'size' => 100]),
    ],
]);
Defensive patterns

Strategy: validation

Validate before calling

if (empty($definition['columns']) || !is_array($definition['columns'])) {
    throw new InvalidArgumentException('createTable requires a non-empty "columns" array');
}

Type guard

function isCreatableTableDefinition(array $definition): bool
{
    return isset($definition['columns'])
        && is_array($definition['columns'])
        && $definition['columns'] !== [];
}

Try / catch

try {
    $connection->createTable($table, $schema, $definition);
} catch (\Phalcon\Db\Exceptions\MissingDefinitionKey $e) {
    throw new RuntimeException("Cannot create table {$table}: " . $e->getMessage(), 0, $e);
}

Prevention

When it happens

Trigger: Calling $adapter->createTable('robots', 'public', ['indexes' => [...]]) with no 'columns'; migration generators emitting definitions without a columns list for empty tables; key misspelled as 'column' or 'fields'.

Common situations: Schema-sync tooling that diffs metadata and produces empty definitions; copying MySQL migration code with a renamed key; programmatic DDL from config files.

Related errors


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