phalcon/cphalcon · error · Phalcon\Db\Exceptions\InvalidIndexColumns
Index definition 'columns' key must be an array
Error message
Index definition 'columns' key must be an array
What it means
Phalcon\Db\Index::__construct() accepts either a plain column list or a definition array detected by the presence of a 'columns' key. In the definition form, 'columns' must itself be an array of column names; a scalar — most commonly a single string — throws InvalidIndexColumns.
Source
Thrown at phalcon/Db/Index.zep:140
/**
* Phalcon\Db\Index constructor.
*
* Accepts either the legacy positional form `(name, columns, type)` or a
* definition-array form `(name, ["columns" => [...], "type" => "...",
* "invisible" => true, ...])`. Detection is based on the presence of a
* `columns` key in the second argument; when present, the third
* positional `type` argument is ignored in favor of the definition.
*/
public function __construct( string name, array columnsOrDefinition, string type = "")
{
var definitionType, invisible, directions, where, concurrent;
let this->name = name;
if isset columnsOrDefinition["columns"] {
if unlikely typeof columnsOrDefinition["columns"] != "array" {
throw new InvalidIndexColumns();
}
let this->columns = columnsOrDefinition["columns"];
if fetch definitionType, columnsOrDefinition["type"] {
let this->type = (string) definitionType;
}
if fetch invisible, columnsOrDefinition["invisible"] {
let this->invisible = (bool) invisible;
}
if fetch directions, columnsOrDefinition["directions"] {
if unlikely typeof directions != "array" {
throw new InvalidIndexDirections();
}
let this->directions = directions;View on GitHub (pinned to b7419de9cd)
Solutions
- Wrap the value in an array: ['columns' => ['user_id']]
- Normalize before construction: $cols = is_array($cols) ? $cols : [$cols]
- Guard definition builders with is_array($definition['columns']) assertions
Example fix
// before
new Index('idx_user', ['columns' => 'user_id', 'type' => 'INDEX']);
// after
new Index('idx_user', ['columns' => ['user_id'], 'type' => 'INDEX']); Defensive patterns
Strategy: type-guard
Validate before calling
if (isset($definition['columns']) && !is_array($definition['columns'])) {
$definition['columns'] = (array) $definition['columns']; // or throw
}
$index = new \Phalcon\Db\Index('idx_user', $definition); Type guard
function isValidIndexDefinition(array $def): bool
{
if (!isset($def['columns'])) {
return true; // positional column-list form
}
return is_array($def['columns']);
} Try / catch
try {
$index = new \Phalcon\Db\Index('idx_user', $definition);
} catch (\Phalcon\Db\Exceptions\InvalidIndexColumns $e) {
throw new InvalidArgumentException('Index columns must be an array of names', 0, $e);
} Prevention
- Always wrap column names in arrays, even for single-column indexes
- Normalize config-sourced definitions: cast scalar 'columns' to an array before use
- Unit-test migration definition builders to emit arrays for every key
When it happens
Trigger: new Index('idx_user', ['columns' => 'user_id', 'type' => 'INDEX']); definitions built from JSON/YAML where a one-element list collapsed to a scalar; ['columns' => implode(',', $cols)].
Common situations: Single-column indexes declared in config files; YAML loaders that inline single-item sequences as plain strings; migration definitions assembled from user input without normalization.
Related errors
- Index definition 'directions' key must be an array
- Index definition 'where' key must be a string
- Referenced table is required
- Foreign key columns are required
- Referenced columns of the foreign key are required
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/ec08e7048236b615.
Report an issue: GitHub.