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

Dialect::select() throws MissingDefinitionKey (extends Phalcon\Db\Exception) when the definition array lacks the 'columns' key. Even for SELECT * the compiler requires an explicit columns entry (e.g. a scalar expression wrapping '*'); it will not guess a default projection. It fails immediately at the top of select(), after the 'tables' check.

Source

Thrown at phalcon/Db/Dialect.zep:609

    {
        return "ROLLBACK TO SAVEPOINT " . name;
    }

    /**
     * Builds a SELECT statement
     */
    public function select( array definition) -> string
    {
        var tables, columns, sql, distinct, joins, where, escapeChar, groupBy,
            having, orderBy, limit, forUpdate, bindCounts;
        array parts;

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

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

        if fetch distinct, definition["distinct"] {
            if distinct {
                let sql = "SELECT DISTINCT";
            } else {
                let sql = "SELECT ALL";
            }
        } else {
            let sql = "SELECT";
        }

        fetch bindCounts, definition["bindCounts"];
        if typeof bindCounts !== "array" {
            let bindCounts = [];
        }

        let escapeChar = this->escapeChar;

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Add a 'columns' entry; for all columns use a scalar expression: definition['columns'] = [['type' => 'scalar', 'value' => '*']] or a list of column names
  2. Default the key in your builder code before calling select(): $definition['columns'] ??= [['type' => 'scalar', 'value' => '*']]
  3. Verify no branch of your definition-building code drops or renames 'columns'
  4. Use Phalcon\Db\QueryBuilder, which normalizes columns for you

Example fix

// before
$sql = $dialect->select(['tables' => ['robots']]);

// after
$sql = $dialect->select([
    'tables'  => ['robots'],
    'columns' => [['type' => 'scalar', 'value' => '*']],
]);
Defensive patterns

Strategy: validation

Validate before calling

$definition['columns'] = $definition['columns'] ?? [['type' => 'scalar', 'value' => '*']];
if (!is_array($definition['columns'])) {
    throw new InvalidArgumentException('"columns" must be an array of expressions');
}

Try / catch

try {
    $sql = $dialect->select($definition);
} catch (\Phalcon\Db\Exceptions\MissingDefinitionKey $e) {
    throw new InvalidArgumentException('Bad select definition: ' . $e->getMessage(), 0, $e);
}

Prevention

When it happens

Trigger: Calling $dialect->select(['tables' => ['robots']]) without a 'columns' key. Also passing columns under a wrong key ('fields', 'select'), or unsetting definition['columns'] in a conditional before the call.

Common situations: Building a generic query layer where columns are optional in the calling API; partial definition arrays assembled from multiple sources; code copied from SELECT examples that omitted the projection.

Related errors


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