phalcon/cphalcon · error · Phalcon\Db\Exceptions\InvalidIndexWhere
Index definition 'where' key must be a string
Error message
Index definition 'where' key must be a string
What it means
In the definition-array form of Index::__construct(), an optional partial-index 'where' key must be a string containing the raw SQL predicate. Any non-string value (array, int, bool) throws InvalidIndexWhere.
Source
Thrown at phalcon/Db/Index.zep:163
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;
let this->type = type;
}
}
/**
* Index columns
*/
public function getColumns() -> arrayView on GitHub (pinned to b7419de9cd)
Solutions
- Pass the predicate as raw SQL: 'where' => 'active = 1'
- Build the string deliberately (e.g. implode(' AND ', $conditions)) instead of passing an array
- Validate with is_string($definition['where']) before constructing Index
Example fix
// before
new Index('idx_active', ['columns' => ['active'], 'where' => ['active' => 1]]);
// after
new Index('idx_active', ['columns' => ['active'], 'where' => 'active = 1']); Defensive patterns
Strategy: type-guard
Validate before calling
if (isset($definition['where']) && !is_string($definition['where'])) {
throw new InvalidArgumentException("Index 'where' must be a raw SQL predicate string, e.g. 'active = 1'");
}
$index = new \Phalcon\Db\Index('idx_active', $definition); Type guard
function isValidIndexDefinition(array $def): bool
{
return !isset($def['columns'])
|| (is_array($def['columns'])
&& (!isset($def['where']) || is_string($def['where'])));
} Try / catch
try {
$index = new \Phalcon\Db\Index('idx_active', $definition);
} catch (\Phalcon\Db\Exceptions\InvalidIndexWhere $e) {
throw new InvalidArgumentException("Partial-index 'where' must be SQL text, not an array", 0, $e);
} Prevention
- Write partial-index predicates as SQL strings ('active = 1'), never field=>value maps
- Finish building predicates into strings before handing them to schema objects
- Add a definition linter for config-driven index definitions
When it happens
Trigger: ['columns' => ['active'], 'where' => ['active' => 1]] passing a conditions array instead of SQL text; 'where' => true or an integer flag; query-builder output that is still an array when handed to Index.
Common situations: Developers expressing the predicate as a field=>value map (common in ORM find() styles); config flags accidentally placed under 'where'; partial-index definitions ported from other tools.
Related errors
- Index definition 'columns' key must be an array
- Index definition 'directions' key must be an array
- 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/1efca4212a0e81eb.
Report an issue: GitHub.