yiisoft/yii2 · error · InvalidArgumentException
Unknown scenario: $scenario
Error message
Unknown scenario: $scenario
What it means
Thrown by yii\base\Model::validate() after beforeValidate() but before any validator executes: the method fetches the scenarios() map (built from the 'on' keys of rules(), always containing the implicit 'default' scenario) and requires the active scenario from getScenario() to be one of its keys. An unknown name means no attribute list exists for it, so the model refuses to validate at all.
Source
Thrown at framework/base/Model.php:374
* the applicable validation rules should be validated.
* @param bool $clearErrors whether to call [[clearErrors()]] before performing validation
* @return bool whether the validation is successful without any error.
* @throws InvalidArgumentException if the current scenario is unknown.
*/
public function validate($attributeNames = null, $clearErrors = true)
{
if ($clearErrors) {
$this->clearErrors();
}
if (!$this->beforeValidate()) {
return false;
}
$scenarios = $this->scenarios();
$scenario = $this->getScenario();
if (!isset($scenarios[$scenario])) {
throw new InvalidArgumentException("Unknown scenario: $scenario");
}
if ($attributeNames === null) {
$attributeNames = $this->activeAttributes();
}
$attributeNames = (array)$attributeNames;
foreach ($this->getActiveValidators() as $validator) {
$validator->validateAttributes($this, $attributeNames);
}
$this->afterValidate();
return !$this->hasErrors();
}
/**
* This method is invoked before validation starts.View on GitHub (pinned to 66f00d18a2)
Solutions
- Declare the scenario in at least one rule: [['email'], 'required', 'on' => [self::SCENARIO_UPDATE]], or override scenarios() explicitly
- Fix the exact spelling and case of the string passed to setScenario() against scenarios() keys
- Fall back to the default scenario for dynamic names: if (!isset($model->scenarios()[$name])) { $model->scenario = Model::SCENARIO_DEFAULT; }
- Keep scenario names in class constants on the model and reference the constants everywhere instead of string literals
Example fix
// before
$model->scenario = 'signupp'; // typo
$model->validate(); // InvalidArgumentException: Unknown scenario: signupp
// after
class User extends \yii\base\Model
{
const SCENARIO_SIGNUP = 'signup';
public function rules()
{
return [
[['email', 'password'], 'required', 'on' => [self::SCENARIO_SIGNUP]],
];
}
}
$model->scenario = User::SCENARIO_SIGNUP;
$model->validate(); Defensive patterns
Strategy: validation
Validate before calling
$scenarios = $model->scenarios();
if (!isset($scenarios[$name])) {
throw new \InvalidArgumentException(
"Scenario '$name' is not declared on " . get_class($model) . '. Known: ' . implode(', ', array_keys($scenarios))
);
}
$model->setScenario($name); Type guard
function scenarioExists(\yii\base\Model $model, string $scenario): bool
{
return isset($model->scenarios()[$scenario]);
} Try / catch
try {
$model->validate();
} catch (\InvalidArgumentException $e) {
// scenario never declared in rules()/scenarios() — log the model class and requested scenario
\Yii::error($e->getMessage(), __METHOD__);
} Prevention
- Declare every scenario callers use in rules() via 'on', or override scenarios(), and cover the list with a unit test
- Store scenario names in model constants and reference the constants instead of string literals
- Assert isset($model->scenarios()[$name]) before assigning dynamic scenario names from request or config data
When it happens
Trigger: Calling $model->setScenario('update')->validate() when no rule in rules() carries 'on' => ['update']; a typo or case mismatch ('Signup' vs 'signup', names are case-sensitive); renaming/removing an 'on' clause while callers still set the old scenario; overriding rules() to return [] which leaves scenarios() with only 'default'.
Common situations: Adding a second form (login vs signup vs update) over one model and forgetting the 'on' key; scenario names set from request or config data that drift from the rules; copying scenario strings between layers where one side was refactored; calling validate() on a model whose rules only use 'except', which does not create scenarios.
Related errors
- Invalid validation rule: a rule must specify both attribute
- There is no type mapping for '{attribute}'.
- The directory does not exist: $path
- Controller class must extend from \yii\base\Controller.
- Unable to determine the entry script file path.
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/6ad80d0ad7584a32.
Report an issue: GitHub.