phalcon/cphalcon · error · Phalcon\Db\Exceptions\InvalidIndexDirections

Index definition 'directions' key must be an array

Error message

Index definition 'directions' key must be an array

What it means

In the definition-array form of Index::__construct(), an optional 'directions' key (per-column ASC/DESC for the index) must be an array. A scalar — e.g. the string 'DESC' instead of ['DESC'] — throws InvalidIndexDirections.

Source

Thrown at phalcon/Db/Index.zep:155

        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;
            }

            if fetch where, columnsOrDefinition["where"] {
                if unlikely typeof where != "string" {
                    throw new InvalidIndexWhere();
                }

                let this->where = where;
            }

            if fetch concurrent, columnsOrDefinition["concurrently"] {
                let this->concurrent = (bool) concurrent;
            }
        } else {
            let this->columns = columnsOrDefinition;

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Pass directions as an array: 'directions' => ['DESC']
  2. Normalize scalars: $dirs = is_array($dirs) ? $dirs : [$dirs]
  3. Validate the definition with a type guard before constructing Index

Example fix

// before
new Index('idx_created', ['columns' => ['created_at'], 'directions' => 'DESC']);

// after
new Index('idx_created', ['columns' => ['created_at'], 'directions' => ['DESC']]);
Defensive patterns

Strategy: type-guard

Validate before calling

if (isset($definition['directions']) && !is_array($definition['directions'])) {
    $definition['directions'] = [$definition['directions']]; // or throw
}
$index = new \Phalcon\Db\Index('idx_created', $definition);

Type guard

function isValidIndexDefinition(array $def): bool
{
    return !isset($def['columns'])
        || (is_array($def['columns'])
            && (!isset($def['directions']) || is_array($def['directions']))
            && (!isset($def['where']) || is_string($def['where'])));
}

Try / catch

try {
    $index = new \Phalcon\Db\Index('idx_created', $definition);
} catch (\Phalcon\Db\Exceptions\InvalidIndexDirections $e) {
    throw new InvalidArgumentException("Index 'directions' must be an array like ['DESC']", 0, $e);
}

Prevention

When it happens

Trigger: ['columns' => ['created_at'], 'directions' => 'DESC']; single-element direction lists collapsed to strings by config loaders; values copied from docs where the array brackets were lost.

Common situations: Descending single-column indexes defined in YAML/JSON; definitions passed through string templates; per-column metadata generated from user input.

Related errors


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