{"record":{"id":"1efca4212a0e81eb","repo":"phalcon/cphalcon","slug":"index-definition-where-key-must-be-a-string","errorCode":null,"errorMessage":"Index definition 'where' key must be a string","messagePattern":"Index definition 'where' key must be a string","errorType":"exception","errorClass":"Phalcon\\Db\\Exceptions\\InvalidIndexWhere","httpStatus":null,"severity":"error","filePath":"phalcon/Db/Index.zep","lineNumber":163,"sourceCode":"            if fetch definitionType, columnsOrDefinition[\"type\"] {\n                let this->type = (string) definitionType;\n            }\n\n            if fetch invisible, columnsOrDefinition[\"invisible\"] {\n                let this->invisible = (bool) invisible;\n            }\n\n            if fetch directions, columnsOrDefinition[\"directions\"] {\n                if unlikely typeof directions != \"array\" {\n                    throw new InvalidIndexDirections();\n                }\n\n                let this->directions = directions;\n            }\n\n            if fetch where, columnsOrDefinition[\"where\"] {\n                if unlikely typeof where != \"string\" {\n                    throw new InvalidIndexWhere();\n                }\n\n                let this->where = where;\n            }\n\n            if fetch concurrent, columnsOrDefinition[\"concurrently\"] {\n                let this->concurrent = (bool) concurrent;\n            }\n        } else {\n            let this->columns = columnsOrDefinition;\n            let this->type    = type;\n        }\n    }\n\n    /**\n     * Index columns\n     */\n    public function getColumns() -> array","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Db/Index.zep#L145-L181","documentation":"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.","triggerScenarios":"['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.","commonSituations":"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.","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"],"exampleFix":"// before\nnew Index('idx_active', ['columns' => ['active'], 'where' => ['active' => 1]]);\n\n// after\nnew Index('idx_active', ['columns' => ['active'], 'where' => 'active = 1']);","handlingStrategy":"type-guard","validationCode":"if (isset($definition['where']) && !is_string($definition['where'])) {\n    throw new InvalidArgumentException(\"Index 'where' must be a raw SQL predicate string, e.g. 'active = 1'\");\n}\n$index = new \\Phalcon\\Db\\Index('idx_active', $definition);","typeGuard":"function isValidIndexDefinition(array $def): bool\n{\n    return !isset($def['columns'])\n        || (is_array($def['columns'])\n            && (!isset($def['where']) || is_string($def['where'])));\n}","tryCatchPattern":"try {\n    $index = new \\Phalcon\\Db\\Index('idx_active', $definition);\n} catch (\\Phalcon\\Db\\Exceptions\\InvalidIndexWhere $e) {\n    throw new InvalidArgumentException(\"Partial-index 'where' must be SQL text, not an array\", 0, $e);\n}","preventionTips":["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"],"tags":["phalcon-db","index","partial-index","schema-definition","migrations"],"backgroundTag":"invalid-index-definition","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}