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

  1. Wrap exactly one condition: ->where(['not', ['status' => 'deleted']])
  2. To negate several conditions, nest them first: ['not', ['and', ['a'=>1], ['b'=>2]]] or ['not', ['or', ...$conds]]
  3. 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

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


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