yiisoft/yii2 · error · InvalidArgumentException

Key "{}" is not a column name and can not be used as a filte

Error message

Key "{}" is not a column name and can not be used as a filter

What it means

findByCondition() routes associative-array conditions through filterCondition(), where every string key must be a valid column: a column of the AR table, or a column prefixed with the table name or with one of the query's declared table aliases (filterValidAliases). Any other string key raises InvalidArgumentException, preventing untrusted input from injecting arbitrary SQL fragments through find conditions.

Source

Thrown at framework/db/ActiveRecord.php:238

     * This method will ensure that an array condition only filters on existing table columns.
     *
     * @param array $condition condition to filter.
     * @param array $aliases
     * @return array filtered condition.
     * @throws InvalidArgumentException in case array contains unsafe values.
     * @throws InvalidConfigException
     * @since 2.0.15
     * @internal
     */
    protected static function filterCondition(array $condition, array $aliases = [])
    {
        $result = [];
        $db = static::getDb();
        $columnNames = static::filterValidColumnNames($db, $aliases);

        foreach ($condition as $key => $value) {
            if (is_string($key) && !in_array($db->quoteSql($key), $columnNames, true)) {
                throw new InvalidArgumentException('Key "' . $key . '" is not a column name and can not be used as a filter');
            }
            $result[$key] = is_array($value) ? array_values($value) : $value;
        }

        return $result;
    }

    /**
     * Valid column names are table column names or column names prefixed with table name or table alias
     *
     * @param Connection $db
     * @param array $aliases
     * @return array
     * @throws InvalidConfigException
     * @since 2.0.17
     * @internal
     */
    protected static function filterValidColumnNames($db, array $aliases)

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Whitelist condition keys against the table schema before calling find: array_intersect_key($condition, array_flip($model::getTableSchema()->getColumnNames()))
  2. Fix the column-name typo so it matches a real column
  3. For joined tables, prefix with the table name or a declared alias: ['{{%order}}.status' => 2]
  4. For anything that is not a plain column, use find()->andWhere() with operator format (['=', 'expr', $value]) instead of findOne/findAll

Example fix

// before
$customers = Customer::findAll($_GET['Customer']); // attacker-controlled keys throw or probe

// after
$schema = Customer::getTableSchema();
$filters = array_intersect_key($_GET['Customer'] ?? [], array_flip($schema->getColumnNames()));
$customers = Customer::findAll($filters);
Defensive patterns

Strategy: validation

Validate before calling

$columns = array_flip($modelClass::getTableSchema()->getColumnNames());
$condition = array_intersect_key($condition, $columns);
$models = $modelClass::findAll($condition);

Try / catch

try {
    $models = Model::findAll($condition);
} catch (yii\base\InvalidArgumentException $e) {
    if (strpos($e->getMessage(), 'is not a column name') !== false) {
        $models = []; // reject untrusted filter keys instead of crashing
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Model::findOne(['usrname' => 'bob']) with a typo; Model::findAll(array_filter($_GET)) letting arbitrary request keys reach the query; keys like 'COUNT(*)' or 'o.status' where 'o' is not an alias present in the query's joins.

Common situations: Passing request data straight into findOne()/findAll(); filtering on a joined table's column while forgetting the alias must appear in the query's join/joinWith; refactors that rename columns; using operator keys like 'like' as hash keys instead of list conditions.

Related errors


AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17). Data as JSON: /api/errors/7d263d17ccf4d0ff. Report an issue: GitHub.