{"record":{"id":"6ad80d0ad7584a32","repo":"yiisoft/yii2","slug":"unknown-scenario-scenario","errorCode":null,"errorMessage":"Unknown scenario: $scenario","messagePattern":"Unknown scenario: \\$scenario","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"framework/base/Model.php","lineNumber":374,"sourceCode":"     * the applicable validation rules should be validated.\n     * @param bool $clearErrors whether to call [[clearErrors()]] before performing validation\n     * @return bool whether the validation is successful without any error.\n     * @throws InvalidArgumentException if the current scenario is unknown.\n     */\n    public function validate($attributeNames = null, $clearErrors = true)\n    {\n        if ($clearErrors) {\n            $this->clearErrors();\n        }\n\n        if (!$this->beforeValidate()) {\n            return false;\n        }\n\n        $scenarios = $this->scenarios();\n        $scenario = $this->getScenario();\n        if (!isset($scenarios[$scenario])) {\n            throw new InvalidArgumentException(\"Unknown scenario: $scenario\");\n        }\n\n        if ($attributeNames === null) {\n            $attributeNames = $this->activeAttributes();\n        }\n\n        $attributeNames = (array)$attributeNames;\n\n        foreach ($this->getActiveValidators() as $validator) {\n            $validator->validateAttributes($this, $attributeNames);\n        }\n        $this->afterValidate();\n\n        return !$this->hasErrors();\n    }\n\n    /**\n     * This method is invoked before validation starts.","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/yiisoft/yii2/blob/66f00d18a29b520f85e8e8f1e32d1e7e7b556cac/framework/base/Model.php#L356-L392","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","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"],"exampleFix":"// before\n$model->scenario = 'signupp'; // typo\n$model->validate(); // InvalidArgumentException: Unknown scenario: signupp\n\n// after\nclass User extends \\yii\\base\\Model\n{\n    const SCENARIO_SIGNUP = 'signup';\n    public function rules()\n    {\n        return [\n            [['email', 'password'], 'required', 'on' => [self::SCENARIO_SIGNUP]],\n        ];\n    }\n}\n\n$model->scenario = User::SCENARIO_SIGNUP;\n$model->validate();","handlingStrategy":"validation","validationCode":"$scenarios = $model->scenarios();\nif (!isset($scenarios[$name])) {\n    throw new \\InvalidArgumentException(\n        \"Scenario '$name' is not declared on \" . get_class($model) . '. Known: ' . implode(', ', array_keys($scenarios))\n    );\n}\n$model->setScenario($name);","typeGuard":"function scenarioExists(\\yii\\base\\Model $model, string $scenario): bool\n{\n    return isset($model->scenarios()[$scenario]);\n}","tryCatchPattern":"try {\n    $model->validate();\n} catch (\\InvalidArgumentException $e) {\n    // scenario never declared in rules()/scenarios() — log the model class and requested scenario\n    \\Yii::error($e->getMessage(), __METHOD__);\n}","preventionTips":["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"],"tags":["php","yii2","model","validation","scenario"],"backgroundTag":"unknown-scenario-name","analyzedSha":"66f00d18a29b520f85e8e8f1e32d1e7e7b556cac","analyzedAt":"2026-08-17T05:17:23.470Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}