phalcon/cphalcon · error · MissingDefinitionKey

The index 'tables' is required in the definition array

Error message

The index 'tables' is required in the definition array

What it means

Phalcon's SQL dialect base class throws MissingDefinitionKey (extends Phalcon\Db\Exception) from Dialect::select() when the definition array passed to the SELECT compiler has no 'tables' key. The dialect cannot build a SELECT without knowing which tables to read, so it fails fast before generating SQL. The same key is required by every dialect (Mysql, Postgresql, Sqlite) since they all inherit this method.

Source

Thrown at phalcon/Db/Dialect.zep:605

    /**
     * Generate SQL to rollback a savepoint
     */
    public function rollbackSavepoint( string name) -> string
    {
        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" {

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Add a non-empty 'tables' entry to the definition array, e.g. definition['tables'] = ['robots'] or a qualified expression array
  2. If the array is built dynamically, assert isset($definition['tables']) before calling select() and fail with your own descriptive error
  3. Check for misspellings or accidental overwriting of the key ('table', 'tableName') right before the call
  4. Prefer Phalcon\Db\QueryBuilder or PHQL, which always emits the 'tables' key for you

Example fix

// before
$sql = $dialect->select([
    'columns' => ['id', 'name'],
]);

// after
$sql = $dialect->select([
    'tables'  => ['robots'],
    'columns' => ['id', 'name'],
]);
Defensive patterns

Strategy: validation

Validate before calling

if (!isset($definition['tables']) || $definition['tables'] === []) {
    throw new InvalidArgumentException('SELECT definition requires a non-empty "tables" entry');
}

Try / catch

try {
    $sql = $dialect->select($definition);
} catch (\Phalcon\Db\Exceptions\MissingDefinitionKey $e) {
    // $e->getMessage() names the missing key, e.g. "The index 'tables' is required..."
    throw new InvalidArgumentException('Bad select definition: ' . $e->getMessage(), 0, $e);
}

Prevention

When it happens

Trigger: Calling $dialect->select(['columns' => ...]) or $adapter->getDialect()->select($definition) with a definition array that omits 'tables'. Also hitting it indirectly when code builds a definition array dynamically and a branch never sets $definition['tables'], or when the key is misspelled ('table', 'fromTable').

Common situations: Hand-assembled definition arrays from query metadata or request input; refactoring a Query Builder pipeline where 'tables' was set on a different array branch; migrating code from an older Phalcon version that silently tolerated partial definitions.

Related errors


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