Title: PHP Error
Last modified: June 2, 2026

---

# PHP Error

 *  [espressivo](https://wordpress.org/support/users/espressivo/)
 * (@espressivo)
 * [3 days, 23 hours ago](https://wordpress.org/support/topic/php-error-709/)
 * Hi Solid Security team,
 * I maintain a client site that’s hitting a fatal PHP error
 * **Environment**
    - WordPress 7.0
    - PHP 8.x
    - Solid Security (better-wp-security)
 * **What happens**
   When the scheduled “digest” notification fires, the plugin crashes
   while building the lockouts summary section of the email. The fatal call is preg_replace()
   being passed a string pattern but an array replacement — PHP 8 requires the pattern
   to also be an array in that case. The user_count tag appears to be passed into
   replace_tag() as an array rather than a scalar.
 * **Error**
   Uncaught TypeError: preg_replace(): Argument #1 ($pattern) must be 
   of type array when argument #2 ($replacement) is an array, string given in …/
   wp-content/plugins/better-wp-security/core/lib.php:983
 * **Stack trace (condensed)**
   preg_replace() — core/lib.php:983 (fatal)ITSEC_Lib::
   replace_tag(‘/{{ $user_coun…/’, ‘user_count’, Array) — core/lib.php:983ITSEC_Lib::
   replace_tags(…) — core/lib.php:996ITSEC_Mail->replace_all(…) — core/lib/class-
   itsec-mail.php:946ITSEC_Mail->add_lockouts_summary(Array, Array) — core/lib/class-
   itsec-mail.php:330ITSEC_Notify->send_daily_digest(…) — core/notify.php:156ITSEC_Notification_Center-
   >send_scheduled_notification(‘digest’)(triggered via the init hook / WP-Cron)
 * Thanks!

Viewing 3 replies - 1 through 3 (of 3 total)

 *  Plugin Support [Pawel [SolidWP Support]](https://wordpress.org/support/users/solidwppawel/)
 * (@solidwppawel)
 * [3 days, 16 hours ago](https://wordpress.org/support/topic/php-error-709/#post-18925961)
 * Hi [@espressivo](https://wordpress.org/support/users/espressivo/),
 * Thanks for the detailed trace, that made this quick to pin down.
 * You’re right that `user_count` is reaching `replace_tag()` as an array, but the
   array is created upstream of the mailer, in `ITSEC_Lockout::get_lockouts()` (`
   core/lockout.php`). When the digest runs, `send_daily_digest()` asks for the 
   lockout counts like this:
 * `$user_count = $itsec_lockout->get_lockouts( 'user', array( 'after' => $last_sent,'
   current' => false, 'return' => 'count' ) );`
 * Inside `get_lockouts()`, the count path is guarded this way:
 * `if ( $is_count && $results ) {`
   `return $results[0]['COUNT'];``}``// ...falls
   through...``return $results;`
 * A `SELECT COUNT(1)` query always returns exactly one row (with `COUNT = 0`) when
   it runs successfully, so under normal conditions you get a scalar `0` back. The
   only way `$results` comes back empty here is when that query fails to execute
   at all, which on this plugin means the lockouts table (`{prefix}itsec_lockouts`)
   is missing or damaged on the site. When that happens the count branch is skipped
   and the method returns an empty `array()` instead of `0`.
 * That empty array then slips past the `if ( $host_count > 0 || $user_count > 0)`
   check in `send_daily_digest()` (in PHP an array compares as greater than `0`),
   so `add_lockouts_summary()` runs with arrays, and they land in `preg_replace()`
   as the replacement value, giving you the PHP 8 TypeError at `lib.php:983`.
 * So the fatal is really a symptom: the digest is blowing up because the lockouts
   table isn’t returning data. To get the site healthy:
    1. Check the table. Adjust the prefix if the site isn’t on `wp_`:
       `SHOW TABLES 
       LIKE 'wp_itsec_lockouts';`and, if it exists:`CHECK TABLE wp_itsec_lockouts;`
    2. If it’s missing or reports as corrupt, regenerate it. Deactivating and reactivating
       Kadence Security re-runs the schema setup and recreates any missing tables without
       touching your settings. If `CHECK TABLE` flagged corruption, run `REPAIR TABLE
       wp_itsec_lockouts;` first.
    3. Let the digest run again (or trigger the cron event manually) and confirm the
       fatal is gone.
 * I’d take a quick database backup before the repair/regenerate step, just as standard
   practice.
 * If the table checks out clean and you still hit this, paste the output of the
   two SQL checks above and I’ll dig in further.
 * Best regards,
 * Pawel P.
 * Liquid Web Software Support
 *  Thread Starter [espressivo](https://wordpress.org/support/users/espressivo/)
 * (@espressivo)
 * [3 days, 12 hours ago](https://wordpress.org/support/topic/php-error-709/#post-18926397)
 * For now deleting and reinstalling the plugin seems to work. I’ll keep you updated
 *  [nlpro](https://wordpress.org/support/users/nlpro/)
 * (@nlpro)
 * [3 hours, 59 minutes ago](https://wordpress.org/support/topic/php-error-709/#post-18930222)
 * Hi [@espressivo](https://wordpress.org/support/users/espressivo/),
 * If you require no further assistance please mark this topic as ‘Resolved’.

Viewing 3 replies - 1 through 3 (of 3 total)

You must be [logged in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fwordpress.org%2Fsupport%2Ftopic%2Fphp-error-709%2F%3Foutput_format%3Dmd&locale=en_US)
to reply to this topic.

 * ![](https://ps.w.org/better-wp-security/assets/icon.svg?rev=3529351)
 * [Kadence Security – Password, Two Factor Authentication, and Brute Force Protection](https://wordpress.org/plugins/better-wp-security/)
 * [Frequently Asked Questions](https://wordpress.org/plugins/better-wp-security/#faq)
 * [Support Threads](https://wordpress.org/support/plugin/better-wp-security/)
 * [Active Topics](https://wordpress.org/support/plugin/better-wp-security/active/)
 * [Unresolved Topics](https://wordpress.org/support/plugin/better-wp-security/unresolved/)
 * [Reviews](https://wordpress.org/support/plugin/better-wp-security/reviews/)

 * 3 replies
 * 3 participants
 * Last reply from: [nlpro](https://wordpress.org/support/users/nlpro/)
 * Last activity: [3 hours, 59 minutes ago](https://wordpress.org/support/topic/php-error-709/#post-18930222)
 * Status: not resolved