2025-06-18 00:26:39 [::1][-][3s6j2ch00pqf5qqcp9vettc94n][error][yii\web\HttpException:400] yii\web\BadRequestHttpException: Missing required parameters: token in 
/app/vendor/yiisoft/yii2/web/Controller.php:173

Stack trace:
#0 /app/vendor/yiisoft/yii2/base/InlineAction.php(54): yii\web\Controller->bindActionParams()
#1 /app/vendor/yiisoft/yii2/base/Controller.php(184): yii\base\InlineAction->runWithParams()
#2 /app/vendor/yiisoft/yii2/base/Module.php(555): yii\base\Controller->runAction()
#3 /app/vendor/yiisoft/yii2/web/Application.php(103): yii\base\Module->runAction()
#4 /app/vendor/yiisoft/yii2/base/Application.php(387): yii\web\Application->handleRequest()
#5 /app/web/index.php(125): yii\base\Application->run()
#6 {main}
2025-06-18 00:26:39 [::1][-][3s6j2ch00pqf5qqcp9vettc94n][error][app\controllers\ErrorController::logException] [
    'message' => 'Missing required parameters: token',
    'code' => 0,
    'stackTrace' => '#0 /app/vendor/yiisoft/yii2/base/InlineAction.php(54): yii\\web\\Controller->bindActionParams()
#1 /app/vendor/yiisoft/yii2/base/Controller.php(184): yii\\base\\InlineAction->runWithParams()
#2 /app/vendor/yiisoft/yii2/base/Module.php(555): yii\\base\\Controller->runAction()
#3 /app/vendor/yiisoft/yii2/web/Application.php(103): yii\\base\\Module->runAction()
#4 /app/vendor/yiisoft/yii2/base/Application.php(387): yii\\web\\Application->handleRequest()
#5 /app/web/index.php(125): yii\\base\\Application->run()
#6 {main}',
    'context' => [
        'errorId' => 'error_685207bf0448b6.48013460',
        'userId' => 'guest',
        'requestUri' => '/index.php?r=site%2Freset-password',
        'statusCode' => 400,
        'exceptionClass' => 'yii\\web\\BadRequestHttpException',
    ],
]

I dont get it...

```
class SiteController extends SeoController
{
	public function actionRequestPasswordReset(): Response|string
	{
		if (!$this->_isGuest)
		{
			return $this->goHome();
		}
		
		// Setup $model.
		$model = new PasswordResetRequestForm();
		$request = \Yii::$app->request;
		
		if (($request->isPost) && ($model->load($request->post()) && $model->validate()))
		{
			// Perform the post-validation action.
			if ($model->process())
			{
				$msg = \Yii::t(
					'app', 
					'<h4 class="alert-heading">Password Reset Email Sent</h4>
					<p>Please check your email inbox for a password reset email. To complete the process, click 
					the provided link, or copy and paste it into your browser.</p>'
				);
				\Yii::$app->session->setFlash('success', $msg);
					
				return $this->goHome();
			}
			
			// Verification failed.
			$msg = \Yii::t(
				'app', 
				'<h4 class="alert-heading">Unable to Reset Password</h4>
				<p>We apologize, but we are unable to reset the password for the provided email address.</p>'
				);	
			\Yii::$app->session->setFlash('error', $msg);
		}
		
		// No need for isGet check, default rendering will be for GET or any unhandled POST.
		return $this->render('request-password-reset-token', [
			//'pageTitle' => $pageTitle,
			'model' => $model,
		]);
	}
}
```

form model
```
<?php
declare(strict_types=1);

namespace app\models\forms;

use Yii;
use yii\base\Model;
use yii\base\Exception as YiiBaseException;
use yii\db\Exception as YiiDbException;

use app\models\User;
use app\helpers\AppHelper;
use app\helpers\ErrorMessageHelper;
use app\helpers\ExceptionLogger;
use app\helpers\LogHelper;
use app\helpers\ParamHelper;
use app\helpers\RoleHelper;

class PasswordResetRequestForm extends Model
{
	public string $email = '';
	
	private string $_appName;
	private string $_emailSupport;
	
        public function __construct(array $config = [])
        {
		$this->_appName = AppHelper::name();
		$this->_emailSupport = ParamHelper::get('email.support');
		
		parent::__construct($config);
	}
	
	public function rules(): array
	{
		return [
			['email', 'trim'],
			['email', 'required'],
			['email', 'email'],
			['email', 'exist',
				'targetClass' => User::class,
				'filter' => function ($query)
				{
					// @var $query \app\models\UserQuery
					$query->active();
				},
				'message' => ErrorMessageHelper::genericFormError(),
				//'message' => \Yii::t('app', 'There is no user with this email address.'),
			],
		];
	}
	
	public function process(): bool
	{
		// @var $user User
		$user = User::find()
			->where(['email' => $this->email])
			->active()
			->notLocked()
			->one();
		
		if ($user === null)
		{
			return false;
		}
		
		$transaction = \Yii::$app->db->beginTransaction();
		try {
			if (!User::isPasswordResetTokenValid($user->password_reset_token))
			{
				$user->generatePasswordResetToken();
				
				if (!$user->save(false, ['password_reset_token']))
				{
					throw new YiiDbException("Failed to save user data to the database.");
				}
			}
			
			// If all saves are successful, commit the transaction.
			$transaction->commit();
			
			$isSent = \Yii::$app->mailer->compose(
					['html' => 'emailPasswordResetToken-html', 'text' => 'emailPasswordResetToken-text'],
					[
						'emailAppName' => $this->_appName,
						'emailSupport' => $this->_emailSupport,
						'emailUser' => $user,
					],
				)
				->setFrom([$this->_emailSupport => \Yii::t(
					'appEmail',
					'{appName} robot',
					['appName' => $this->_appName])
				])
				->setTo($user->email)
				->setSubject(\Yii::t(
					'appEmail',
					'Password reset for {appName}',
					['appName' =>  $this->_appName])
				)
				->send();
				
			if (!$isSent)
			{
				throw new YiiBaseException("The email could not be sent to {$recipientEmail}.");
			}
			
			return true;
		}
		catch (\Throwable $e)
		{
			// An error occurred; roll back the transaction.
			$transaction->rollBack();
			
			// Use the ExceptionLogger to handle and log the exception.
			ExceptionLogger::log($e, 'password_reset_error_');
		}
		
		return false;
	}
}

```

email

```
<?php
declare(strict_types=1);

use yii\helpers\Html;

use app\helpers\EmailHelper;
use app\helpers\ValueHelper;

$appName = Html::encode($emailAppName);
$support = Html::encode($emailSupport);
$fullName = trim(Html::encode($emailUser->firstname) . ' ' . Html::encode($emailUser->lastname));
$recipient = ((ValueHelper::isSetNotNull($emailUser->firstname) || ValueHelper::isSetNotNull($emailUser->lastname)) 
	? $fullName 
	: Html::encode($emailUser->email)
);

// Variables only for this view:
$resetLink = \Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $emailUser->password_reset_token]);
?>


<?= EmailHelper::styledParagraphs([
	\Yii::t('appEmail', 'Dear {recipient},', ['recipient' => $recipient]),
	\Yii::t('appEmail', 'Follow the link below to reset your password:'),
	Html::a(Html::encode($resetLink), $resetLink),
	\Yii::t('appEmail', 'If you have any issues, please contact our support at {support}',['support' => $support]),
	\Yii::t('appEmail', 'Thank you,') . '<br>' . $appName,
], allowHtml: true); ?>

```

which than driects the user to site/reset-password

```
	public function actionResetPassword(string $token): Response|string
	{
		try
		{
			$model = new ResetPasswordForm($token);
		}
		catch (YiiInvalidArgumentException $e)
		{
			throw new YiiBadRequestHttpException($e->getMessage());
		}
		
		$request = \Yii::$app->request;
		if (($request->isPost) && ($model->load($request->post()) && $model->validate()))
		{
			// Perform the post-validation action.
			if ($model->process())
			{
				$msg = \Yii::t(
					'app',
					'<h4 class="alert-heading">New Password Saved</h4>
					<p>Your new password has been successfully saved.</p>'
				);
				\Yii::$app->session->setFlash('success', $msg);
				
				return $this->goHome();
			}
			else
			{
				\Yii::$app->session->setFlash('error', ErrorMessageHelper::genericError());
			}
		}
		
		// No need for isGet check, default rendering will be for GET or any unhandled POST.
		return $this->render('reset-password', [
			'model' => $model,
		]);
	}
```

ResetPasswordForm:

```
<?php
declare(strict_types=1);

namespace app\models\forms;

use Yii;
use yii\base\Model;
use yii\base\InvalidArgumentException as YiiBaseInvalidArgumentException;
use yii\db\Exception as YiiDbException;

use app\models\User;
use app\helpers\AppHelper;
use app\helpers\ExceptionLogger;
use app\helpers\LogHelper;
use app\helpers\ParamHelper;
use app\helpers\RoleHelper;

class ResetPasswordForm extends Model
{
	public string $password = '';
	public string $password_repeat = '';
	
	private int $_userPasswordMinLength = 0;
	
	private ?User $_user = null;
	
	private string $_appName;
	private string $_emailSupport;
	
	public function __construct(string $token, array $config = [])
	{
		if (empty($token) || !is_string($token))
		{
			$msg = \Yii::t('app', 'Password reset token cannot be blank.');
			throw new YiiBaseInvalidArgumentException($msg);
		}
		
		// Assign user object class propert to a local variable
		$this->_user = User::findByPasswordResetToken($token);
		
		if (!$this->_user)
		{
			$msg = \Yii::t('app', 'Wrong password verification reset token.');
			throw new YiiBaseInvalidArgumentException($msg);
		}
		
		$this->_appName = AppHelper::name();
		$this->_emailSupport = ParamHelper::get('email.support');
		$this->_userPasswordMinLength = ParamHelper::get('user.passwordMinLength');
		
		parent::__construct($config);
	}
	
	public function rules(): array
	{
		return [
			[['password', 'password_repeat'], 'required'],
			[['password', 'password_repeat'], 'string', 'min' => $this->_userPasswordMinLength],
			['password_repeat','compare','compareAttribute' => 'password'],
		];
	}
	
	public function attributeLabels(): array
	{
		return [
			'password' => \Yii::t('app', 'Password'),
			'password_repeat' => \Yii::t('app', 'Confirm Password'),
		];
	}
	
	public function process(): bool
	{
		$transaction = \Yii::$app->db->beginTransaction();
		try
		{
			$this->_user->setPassword($this->password_repeat);
			//$this->_user->removePasswordResetToken();// TODO is this causing the issue of the missing token?
			$this->_user->generateAuthKey();
			
			// Use 'false' to skip validation as model is already validated.
			if (!$this->_user->save(false, ['password_hash', /*'password_reset_token',*/ 'auth_key']))
			{
				throw new YiiDbException("Failed to save user data to the database.");
			}
			
			// If all saves are successful, commit the transaction.
			$transaction->commit();
			
			$isSent = \Yii::$app->mailer->compose(
					['html' => 'emailAccountPasswordChanged-html', 'text' => 'emailAccountPasswordChanged-text'],
					[
						'emailAppName' => $this->_appName,
						'emailSupport' => $_emailSupport,
						'emailUser' => $this->_user,
					],
				)
				->setFrom([$this->_emailSupport => \Yii::t(
					'appEmail',
					'{appName} robot',
					['appName' => $this->_appName])
				])
				->setTo($this->_user->email)
				->setSubject(\Yii::t(
					'appEmail',
					'Password for {appName} account has been changed',
					['appName' =>  $this->_appName])
				)
				->send();
				
			if (!$isSent)
			{
				throw new YiiBaseException("The email could not be sent to {$recipientEmail}.");
			}
			
			return true;
		}
		catch (\Throwable $e)
		{
			// An error occurred; roll back the transaction.
			$transaction->rollBack();
			
			// Use the ExceptionLogger to handle and log the exception.
			ExceptionLogger::log($e, 'reset_form_error_');
		}
		
		return false;
	}
}

```

What is causing the error?