passbolt/passbolt_api · warning · StopException

Password expiry is not activated.

Error message

Password expiry is not activated.

What it means

PasswordExpiryPoliciesGetOwnersOfResourcesAboutToExpireService::notifyUsers() first loads password expiry settings and requires the 'expired' (password expiry) feature to be enabled. When isPasswordExpiryFeatureEnabled() is false it throws StopException, since notifying about expiring resources is meaningless with expiry disabled.

Solutions

  1. Enable password expiry via the admin UI or the password expiry policies settings endpoint so isPasswordExpiryFeatureEnabled() returns true
  2. Remove/disable the scheduled job that calls notifyUsers() if the feature is intentionally off
  3. Check the password_expiry_settings table contains an enabled configuration and run the migration if the table is missing

Example fix

// before
// no password_expiry_settings row -> feature considered disabled, cron still runs
// after
bin/cake passbolt password_expiry_policies enable  # or set {"disabled":false} via settings API before scheduling notifications
Defensive patterns

Strategy: validation

Validate before calling

$settings = (new PasswordExpiryPoliciesGetSettingsService())->get();
if (!$settings->isPasswordExpiryFeatureEnabled()) {
    // skip notify job
    return;
}

Type guard

$featureEnabled = $settings !== null && $settings->isPasswordExpiryFeatureEnabled();

Try / catch

try {
    $owners = $service->notifyUsers();
} catch (StopException $e) {
    if ($e->getMessage() === 'Password expiry is not activated.') {
        // disable the job or enable the feature
    }
}

Prevention

When it happens

Trigger: Running the notify/expiry-email job (e.g. 'passbolt notify_user_of_resources_expiring' style command or scheduled email digest) when the passwordExpiry disabled setting is true (or absent and defaulting to disabled) in password_expiry_settings.

Common situations: EE Password Expiry feature not purchased/enabled but a cron job still triggers the notification; settings table lacking the 'disabled'=>false entry after migration.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/f7d1db81f640ec30. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/PasswordExpiryPolicies/src/Service/Resources/PasswordExpiryPoliciesGetOwnersOfResourcesAboutToExpireService.php:62

     * @param \Passbolt\PasswordExpiry\Service\Settings\PasswordExpiryGetSettingsServiceInterface $settingsService Get password expiry service
     */
    public function __construct(PasswordExpiryGetSettingsServiceInterface $settingsService)
    {
        $this->settingsService = $settingsService;
    }

    /**
     * Notify the users about their passwords expiring today or in N days
     *
     * @return \Cake\ORM\Query
     * @throws \Cake\Console\Exception\StopException if the settings are not enabled
     */
    public function notifyUsers(): Query
    {
        $settings = $this->settingsService->get();

        if (!$settings->isPasswordExpiryFeatureEnabled()) {
            throw new StopException(__('Password expiry is not activated.'));
        }

        // Notify resource owners that some resources are about to expire
        $expiryNotificationInDays = EmailNotificationSettings::get('send.password.aboutToExpire') ?
            $settings->getExpiryNotification() : null;

        // Notify resource owners that resources are expiring today
        $notifyIfExpiresToday = (bool)EmailNotificationSettings::get('send.password.expire');

        $users = $this->getUsersToNotify($expiryNotificationInDays, $notifyIfExpiresToday);
        $users
            ->find('locale')
            ->contain(['Profiles' => AvatarsTable::addContainAvatar()]);

        $this->dispatchEvent(
            self::NOTIFY_ABOUT_EXPIRED_RESOURCES_EVENT_NAME,
            [
                'users' => $users->all()->toArray(),

View on GitHub (pinned to 31c1bbc10f)