yiisoft/yii2 · error · yii\base\InvalidArgumentException
Operator '$operator' requires exactly one operand.
Error message
Operator '$operator' requires exactly one operand.
What it means
yii\db\conditions\NotCondition::fromArrayDefinition() (framework/db/conditions/NotCondition.php:53) builds ['not', X] conditions and requires count($operands) === 1 — exactly one condition to negate. Unlike the isset()-based guards in the other condition classes, a null operand is acceptable here; extra elements or none at all are not.
Source
Thrown at framework/db/conditions/NotCondition.php:53
$this->condition = $condition;
}
/**
* @return mixed
*/
public function getCondition()
{
return $this->condition;
}
/**
* {@inheritdoc}
* @throws InvalidArgumentException if wrong number of operands have been given.
*/
public static function fromArrayDefinition($operator, $operands)
{
if (count($operands) !== 1) {
throw new InvalidArgumentException("Operator '$operator' requires exactly one operand.");
}
return new static(array_shift($operands));
}
}
View on GitHub (pinned to 66f00d18a2)
Solutions
- Wrap exactly one condition: ->where(['not', ['status' => 'deleted']])
- To negate several conditions, nest them first: ['not', ['and', ['a'=>1], ['b'=>2]]] or ['not', ['or', ...$conds]]
- When negating dynamic input, build the inner condition separately and wrap it once: ['not', $inner]
Example fix
// before $cond = ['not', ['status' => 'draft'], ['archived' => 1]]; // 2 operands -> throws // after $cond = ['not', ['and', ['status' => 'draft'], ['archived' => 1]]];
Defensive patterns
Strategy: validation
Validate before calling
function buildNotCondition(array $inner): array
{
if (count($inner) === 0) {
return []; // nothing to negate
}
// collapse a list of conditions into ONE operand for NOT
$operand = count($inner) === 1
? $inner[0]
: array_merge(['and'], $inner);
return ['not', $operand];
}
$query->andWhere(buildNotCondition($conditions)); Try / catch
try {
$rows = $query->all();
} catch (\yii\base\InvalidArgumentException $e) {
\Yii::warning('Malformed NOT condition: ' . $e->getMessage(), __METHOD__);
$rows = [];
} Prevention
- NOT takes exactly one nested condition — wrap multiple conditions in ['and', ...] or ['or', ...] first
- Never spread arrays into ['not', ...$conds]
- Guard dynamic negation with a count() check before adding the operator
When it happens
Trigger: ['not'] with nothing to negate; ['not', ['a'=>1], ['b'=>2]] passing several conditions; programmatically negating a dynamically built list where array_merge/array flattening turns one nested condition into multiple operands.
Common situations: Developers expecting NOT to accept a list like AND/OR do; building ['not', ...$conditions] spreads multiple operands after the operator; negating filter input that may be an empty array (['not', []] passes count===1 and builds NOT (1=0)? — no, it builds NOT of an empty condition, which yields unexpected SQL rather than an exception).
Related errors
- Operator '$operator' requires three operands.
- Operator '$operator' requires two operands.
- Operator '$operator' requires two operands.
- Operator '$operator' requires two operands.
- Subquery for EXISTS operator must be a Query object.
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/a2bbd2da58e379ed.
Report an issue: GitHub.