Update WP Rocket to 3.23.2.2 before WordPress 7.1
EN

Update WP Rocket to 3.23.2.2 before WordPress 7.1

Last verified: September 1, 2026
11 min read
News
500+ WP projects
Security auditor

WPPoland (Mariusz Szatkowski) updates WP Rocket to 3.23.2.2 on staging before WordPress 7.1. Versions 3.23.2.1 and earlier fatal on every request: Uncaught TypeError: substr(): Argument #1 ($string) must be of type string, int given in Cloudflare.php:562. The GitHub report landed 6 July 2026. WordPress 7.1 Mary Lou shipped 19 August. The plugin fix shipped 20 August. Plugin first, then core.

#What crashed

You updated to WordPress 7.1 and the site went white. wp-admin is down. admin-ajax is down. REST is down. WP-CLI dies with the same stack. The PHP log repeats one line on every request:

PHP Fatal error: Uncaught TypeError: substr(): Argument #1 ($string) must be of type string, int given in .../wp-rocket/inc/ThirdParty/Plugins/CDN/Cloudflare.php:562

Wordify reproduced it end to end on a test site and published the stack on 20 August 2026. The fatal fires on init, while WordPress is still booting, so the front end and the dashboard die together. Turning on WP_DEBUG does not always print anything on screen. The error log is the reliable place.

This is a WP Rocket bug, not a host bug, and not “WordPress 7.1 is broken.” Sites without WP Rocket did not hit this TypeError. Sites on WP Rocket 3.23.2.2 do not hit it. The changelog line is: “Fixed the Fatal Type Error appearing after update to WordPress Core 7.1 in some configurations.”

The code path lives in the Cloudflare compatibility module. You do not need a Cloudflare zone for it to run. Wordify was explicit: the module runs on every request whether or not the Cloudflare plugin is installed.

#Three pieces that are harmless alone

WordPress 7.1 changed how hook callback IDs are built. Trac ticket 65919 is the core change. Up to 7.0.x, _wp_filter_build_unique_id() used spl_object_hash(), a 32-character hex string. 7.1 switched to spl_object_id(), a small integer cast to string. David Levine at rtCamp later pointed at the same ticket when the official WordPress X account said “this wasn’t a bug in 7.1.” The TypeError is in the plugin. The type of the key changed in core. Both statements can be true.

PHP then stores numeric string keys as integers. When "5292" is used as an array key in $wp_filter, PHP keeps it as 5292. After 7.1, a closure hooked to an action has an integer key. Before 7.1, every key was a string.

WP Rocket assumes those keys are strings, with strict_types=1 in Cloudflare.php. On init it walks callbacks on deleted_post and transition_post_status and calls substr() on each key. Strict types refuse to coerce the integer. Fatal.

Wordify published the loop:

foreach ( $original_wp_filter[ $priority ] as $key => $config ) {
    if ( substr( $key, - strlen( $method ) ) !== $method ) {

A clean WordPress plus WP Rocket often survives. Austin Ginder found that. Add a plugin that hooks a closure on deleted_post at priority 10, or on transition_post_status at PHP_INT_MAX, and the next request dies. Elementor Pro is the widespread example. Contact Form 7 Redirection is another. The second plugin is doing nothing wrong. Hooking a closure is normal WordPress.

Matt Cromwell noted the irony on X: the core change was a performance improvement, which is the product WP Rocket sells.

#The six-week GitHub report

wp-media/wp-rocket issue 8596 was filed 6 July 2026, during the 7.1 beta. The report named the TypeError and suggested a one-line string cast. The Repository, 21 August: WP Rocket reviewed it the same day, QA could not reproduce it in automated tests, and the issue dropped. It was never assigned an owner.

WordPress 7.1 shipped 19 August 2026, closing day of WordCamp US in Phoenix. Ginder posted the same day: WP Rocket sites in the Anchor Hosting fleet went offline after the 7.1 bump. He patched the plugin by hand to bring them back.

Two more GitHub issues, 8740 and 8741, landed the day after release. WP Rocket posted an advisory: do not update to 7.1 until a fix is ready, with a support article at docs.wp-rocket.me/article/1927. Later on 20 August they shipped 3.23.2.2, the one-line cast from the July report. Wordify verified the fix on the same crash they had restaged on 3.23.2.1.

The GitHub pull is wp-media/wp-rocket#8745.

#Who went down

Ginder’s fleet numbers, 20 August: 124 of 332 production sites running WP Rocket fatals, 37 percent. Every crash was WordPress 7.1 + PHP 8.x + Cloudflare.php.

WP Rocket’s later post-mortem, covered by The Repository on 27 August, estimated about 27 percent of its user base at risk and about 10 percent actually hit. CEO Rémy Lamiot said Elementor Pro, despite the install base and despite being one of the triggers, was not on the compatibility list they tested. The July report had no owner. “This cost real time and real trust,” he wrote.

Those two percentages are not the same measurement. Ginder counted a managed fleet that already ran WP Rocket. WP Rocket counted its whole user base, including sites that never took 7.1 that week and sites without the second plugin. Quote both. Do not average them.

Wordify’s first customer site updated core at 01:55 UTC. The first fatal hit the log three seconds later. Support deactivated the plugin. About 35 minutes end to end, most of it diagnosis, because nobody had yet joined “7.1” to “WP Rocket.”

Andrew Hoyer wrote that he had warned his team about 7.1 and still woke up to dozens of broken sites. His line: test alpha, beta and RC on your own stack rather than trusting the vendor. Steve Jones asked whether people were updating production the hour a major landed, with no rollback. Both questions are the job of a maintenance retainer. They are not a brand argument.

#Safe order

If the site is still on WordPress 7.0.x and WP Rocket is older than 3.23.2.2:

  1. Clone to staging.
  2. Update WP Rocket to 3.23.2.2 on staging. Confirm wp-admin and a logged-out front page load.
  3. Then take WordPress 7.1 on staging. Hit login, checkout if WooCommerce, a form, cron.
  4. Repeat the same order on production: plugin first, core second.

If auto-updates already took 7.1 and the site is white, skip the happy path. Deactivate first.

Do not reactivate 3.23.2.1 on 7.1. WP Media’s support article is explicit: if no update appears in the plugin list, follow their missing-update guide. Reactivating the broken version takes the site down again.

Very old WP Rocket builds that predate the Cloudflare.php loop are unaffected. Wordify put the affected band at roughly 3.16 through 3.23.2.1. If you are unsure, update to 3.23.2.2 anyway. That is the version with the string cast.

PieceVersion / dateRole
WordPress7.1 Mary Lou, 19 Aug 2026Switched hook IDs to spl_object_id (Trac 65919)
PHP8.x with strict_types=1 in the plugin fileInteger key into substr() is a TypeError, not a warning
WP Rocket3.16 through 3.23.2.1Cloudflare.php:562 walks hook keys on init
WP Rocket3.23.2.2, 20 Aug 2026One-line string cast from GitHub 8596
Trigger pluginElementor Pro, CF7 Redirection, othersClosure on deleted_post or transition_post_status

We already covered what 7.1 actually shipped, and what it cut, in the WordPress 7.1 roadmap note. The iframed post editor is a separate developer break. Details in the iframed editor note. This piece is only the Rocket fatal.

#If wp-admin is already white

Do not delete Cloudflare.php. Wordify: the class is wired into the plugin container, and removing the file swaps this fatal for another.

WP-CLI. WP-CLI loads plugins, so a bare wp plugin deactivate wp-rocket dies. Skip the plugin while you deactivate it:

wp plugin deactivate wp-rocket --skip-plugins=wp-rocket

SFTP. Rename wp-content/plugins/wp-rocket to wp-rocket.off. WordPress treats a renamed folder as deactivated on the next request.

Then update to 3.23.2.2 from wp-admin, which is alive again, and reactivate.

Rollback to 7.0.4 from a pre-update backup also restores the site. It is the slower path. It discards the 7.1 files you already wrote to disk. Use it when you cannot reach SFTP or WP-CLI.

A host-level page cache (LiteSpeed, nginx FastCGI, Cloudflare cache of HTML) can keep serving a last good page to anonymous visitors while wp-admin is dead. That hides the outage from some customers and delays the ticket. Check the error log, not only the homepage.

#How we test a core bump

WPPoland (Mariusz Szatkowski) treats a major as a three-layer check, not a calendar event.

Staging is a clone, not a subdirectory on production. Same PHP, same object cache, same plugins. We take the plugin updates that have a known incompatibility first. For 7.1 that list started with WP Rocket 3.23.2.2. Then core. Then a smoke list: login, a save in the post editor (now always iframed), WooCommerce cart and checkout if the site has them, a form POST, a cron run.

We do not trust “WP Rocket said they tested 7.1.” They did test. Their suite missed the integer key plus a second-plugin closure. Ginder’s clean install did not crash. The combination did. The combination is what a client site actually is.

On production we keep a named backup from before the bump and a 15-minute window where someone is watching the error log, not only uptime ping. A white homepage with a 200 from HTML cache is not a pass.

A typical client clone in this shop is WordPress + WooCommerce or Elementor + WP Rocket + a form plugin. That is the combination Ginder and Wordify described. We do not wait for the vendor’s “we tested 7.1” tweet. We take 7.1 on the clone, request / and /wp-admin/, and grep the PHP log for TypeError and Cloudflare.php. If the log is silent and both URLs return 200 without a plugin skip, the bump can go to production in the same order.

PHP version is part of the clone. The TypeError is a PHP 8 strict-types failure. A host still on PHP 7.4 would not throw this particular fatal. That is not a reason to stay on 7.4. It is a reason to test 8.2 or 8.3 with the same plugin set you run in production, not with a bare WordPress.

That is the WordPress maintenance retainer in one paragraph. Staging first. Plugin first when the vendor has a pin. Core second. Health check after. Written quote after a short brief.

If the public surface already sits on Cloudflare Workers or Pages, the PHP fatal still kills wp-admin and any origin route. Edge HTML cache is not a substitute for a plugin that fatals on init. The Cloudflare edge pillar is the delivery layer. This incident is the origin layer.

#Auto-updates and 7.1.1

Wordify warned that 7.1 auto-updates were rolling the same week. A site nobody touched could still go from fine to down overnight.

Adam Silverstein opened Trac 65920 on 20 August: a GitHub Actions workflow to test the top 100 directory plugins against unreleased WordPress. Draft PR 13198, milestoned for 7.2. He noted in the ticket that this exact incident would not have been caught, because WP Rocket is premium and the directory API covers free plugins. The same class of type-change fatal can still hit a free plugin with millions of installs. That is the point of the workflow.

Aaron Jorbin called for volunteers to manage 7.1.x. 7.1.1 was pencilled between 1 and 24 September 2026. Treat 7.1.1 the same way: staging, then production. If 65919’s integer keys get a compatibility shim in 7.1.1, that is extra insurance. It is not a reason to skip 3.23.2.2.

Jeffrey Paul backed Silverstein’s ticket: repeated fatals after majors are inside core’s sphere of concern, even when the broken file sits in a plugin. That is the honest split. Core can test directory plugins. Core cannot test premium plugins it does not have. The site owner, or the person on the retainer, still owns the clone.

#What we are not claiming

We are not saying dump WP Rocket. 3.23.2.2 is the current build with the cast. Cache plugins still earn their keep on PHP origins.

We are not saying skip WordPress 7.1. Responsive styling, client-side media, the persistent admin bar, and the iframed editor shipped. The roadmap note lists what landed and what did not.

We are not quoting WP Rocket’s prices. Third-party licence fees are their list. Our maintenance work is an individual quote.

We are not inventing a percentage for “the whole internet.” Ginder’s 37 percent is a fleet. WP Rocket’s 10 percent is their estimate of their user base. Both are sourced. Neither is a census.

Last updated 1 September 2026. Sources: The Repository (21 and 27 August 2026), Wordify’s stack-trace write-up (20 August), GitHub issue 8596 and pull 8745, Trac 65919 and 65920, WP Rocket 3.23.2.2 changelog and support article 1927, Austin Ginder on X, Rémy Lamiot’s post-mortem quotes via The Repository.

Next step

Turn the article into an actual implementation

This block strengthens internal linking and gives readers the most relevant next move instead of leaving them at a dead end.

Article FAQ

Frequently asked questions

Practical answers to apply the topic in real execution.

SEO-readyGEO-readyAEO-ready5 Q&A
wp rocket wordpress 7.1#
WP Rocket 3.23.2.1 and earlier fatals on WordPress 7.1 when Cloudflare.php calls substr() on an integer hook key. WPPoland (Mariusz Szatkowski) updates WP Rocket to 3.23.2.2 on staging first, then WordPress 7.1. If the site is already white, deactivate the plugin over SFTP or WP-CLI with --skip-plugins=wp-rocket, then update.
Does WP Rocket work with WordPress 7.1?#
Yes, from WP Rocket 3.23.2.2, released 20 August 2026. Versions from about 3.16 through 3.23.2.1 are the ones that crash. A clean WordPress plus WP Rocket alone often does not crash. Add a plugin that hooks a closure on deleted_post or transition_post_status, commonly Elementor Pro, and the next request is a TypeError.
I do not use Cloudflare. Why did WP Rocket take the site down?#
WP Rocket's Cloudflare compatibility module runs on init on every request, whether or not the Cloudflare plugin is installed. Wordify reproduced that. You do not need a Cloudflare account for Cloudflare.php:562 to fire.
How do I recover if wp-admin is white?#
Do not delete Cloudflare.php inside the plugin. That swaps one fatal for another. Deactivate the whole plugin: wp plugin deactivate wp-rocket --skip-plugins=wp-rocket, or rename wp-content/plugins/wp-rocket over SFTP. Then update to 3.23.2.2 and reactivate. Rolling core back to 7.0.4 also works. It is slower and throws away the 7.1 work.
Should I turn off WordPress auto-updates?#
Not as a religion. Auto-updates without a staging clone and a health check after the bump are how a Wednesday core release becomes a Thursday outage. WPPoland tests core, plugins and PHP together on staging. Production gets the plugin bump first, then core. Written quote for that retainer after a short brief.

Need an FAQ tailored to your industry and market? We can build one aligned with your business goals.

Let’s discuss

Related Articles