laravel/framework · error · UnexpectedValueException

User must implement CanResetPassword interface.

Error message

User must implement CanResetPassword interface.

What it means

Thrown by PasswordBroker::getUser() when the user retrieved by credentials does not implement the Illuminate\Contracts\Auth\CanResetPassword contract. The password reset broker calls getEmailForPasswordReset() and getRememberTokenName()-style methods on the user, so the contract is required for the reset flow.

Solutions

  1. Make the User model implement Illuminate\Contracts\Auth\CanResetPassword and use the Illuminate\Auth\Passwords\CanResetPassword trait.
  2. Extend Illuminate\Foundation\Auth\User (which already wires the trait and contract).
  3. Ensure the auth provider's 'model' points at a class that satisfies the contract.
  4. If using a non-Eloquent user, implement getEmailForPasswordReset() and sendPasswordResetNotification() manually.

Example fix

// before
use Illuminate\Database\Eloquent\Model;
class Member extends Model {} // no CanResetPassword

// after
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Auth\Passwords\CanResetPassword;
class Member extends Model implements CanResetPasswordContract
{
    use CanResetPassword;
}
Defensive patterns

Strategy: type-guard

Validate before calling

// PHP — assert the user model satisfies the contract before reset flow
if (! is_subclass_of($userModel, \Illuminate\Contracts\Auth\CanResetPassword::class)) {
    throw new \RuntimeException("{$userModel} must implement CanResetPassword to support password reset.");
}
Password::broker()->sendResetLink($credentials);

Type guard

function userSupportsReset(string $modelClass): bool {
    return is_subclass_of($modelClass, \Illuminate\Contracts\Auth\CanResetPassword::class);
}

Try / catch

try {
    Password::broker()->sendResetLink($credentials);
} catch (\UnexpectedValueException $e) {
    report('User model does not implement CanResetPassword: '.$e->getMessage());
    return back()->withErrors(['email' => 'Password reset is not available for this account type.']);
}

Prevention

When it happens

Trigger: Running a password reset (Password::sendResetLink / Password::reset) where the resolved user model class does not implement CanResetPassword (typically by failing to extend Illuminate\Foundation\Auth\User or Illuminate\Database\Eloquent\Model + the trait).

Common situations: A custom User model that extends a bare Eloquent\Model without the Illuminate\Auth\Passwords\CanResetPassword trait and the CanResetPassword contract; swapping the auth provider to return a different DTO/user class that lacks the contract; legacy upgrades where the contract was added in a newer version.

Related errors


AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11). Data as JSON: /api/errors/f1e51384f08e8a4e. Report an issue: GitHub.

Appendix: source

Thrown at src/Illuminate/Auth/Passwords/PasswordBroker.php:183

        return $user;
    }

    /**
     * Get the user for the given credentials.
     *
     * @param  array  $credentials
     * @return \Illuminate\Contracts\Auth\CanResetPassword|null
     *
     * @throws \UnexpectedValueException
     */
    public function getUser(#[\SensitiveParameter] array $credentials)
    {
        $credentials = Arr::except($credentials, ['token']);

        $user = $this->users->retrieveByCredentials($credentials);

        if ($user && ! $user instanceof CanResetPasswordContract) {
            throw new UnexpectedValueException('User must implement CanResetPassword interface.');
        }

        return $user;
    }

    /**
     * Create a new password reset token for the given user.
     *
     * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user
     * @return string
     */
    public function createToken(CanResetPasswordContract $user)
    {
        return $this->tokens->create($user);
    }

    /**
     * Delete password reset tokens of the given user.

View on GitHub (pinned to e0f6eb3518)