WPPoland (Mariusz Szatkowski) aktualizuje WP Rocket do 3.23.2.2 na stagingu przed WordPressem 7.1. Wersje 3.23.2.1 i starsze wywalają fatal przy każdym żądaniu: Uncaught TypeError: substr(): Argument #1 ($string) must be of type string, int given w Cloudflare.php:562. Raport na GitHubie wpadł 6 lipca 2026. WordPress 7.1 Mary Lou wyszedł 19 sierpnia. Poprawka wtyczki 20 sierpnia. Najpierw wtyczka, potem rdzeń.
Co padło
Zaktualizowałeś do WordPressa 7.1 i strona zeszła na biały ekran. wp-admin leży. admin-ajax leży. REST leży. WP-CLI umiera na tym samym stosie. Log PHP powtarza jedną linię przy każdym żądaniu:
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 odtworzył to od początku do końca na stronie testowej i opublikował stos 20 sierpnia 2026. Fatal odpala się na init, gdy WordPress jeszcze się uruchamia, więc front i kokpit padają razem. Włączenie WP_DEBUG nie zawsze coś wypisze na ekranie. Pewnym miejscem jest log błędów.
To błąd WP Rocket, nie błąd hostingu i nie teza, że „WordPress 7.1 jest zepsuty”. Strony bez WP Rocket tego TypeError nie dostały. Strony na WP Rocket 3.23.2.2 też go nie dostają. Linia w changelogu: “Fixed the Fatal Type Error appearing after update to WordPress Core 7.1 in some configurations.”
Ścieżka kodu siedzi w module zgodności Cloudflare. Strefa Cloudflare nie jest do tego potrzebna. Wordify napisał wprost: moduł odpala się przy każdym żądaniu, niezależnie od tego, czy wtyczka Cloudflare jest zainstalowana.
Na polskim hostingu ten sam objaw łatwo pomylić z awarią panelu. cyber_Folks i home.pl w nocy czasu CET serwują autoaktualizację rdzenia, a rano w panelu widać tylko „strona nie odpowiada”. PHP fatal nie zawsze ląduje w mailu z monitoringu. Otwórz error_log na koncie FTP albo w logach PHP-FPM, zanim zaczniesz restartować vhost.
Trzy elementy, które same nic nie psują
WordPress 7.1 zmienił sposób budowania identyfikatorów callbacków hooków. Ticket Trac 65919 to zmiana w rdzeniu. Do 7.0.x _wp_filter_build_unique_id() używało spl_object_hash(), 32-znakowego stringa hex. 7.1 przeszło na spl_object_id(), małą liczbę całkowitą rzutowaną na string. David Levine z rtCamp wskazał później ten sam ticket, gdy oficjalne konto WordPressa na X napisało, że „to nie był błąd w 7.1”. TypeError jest we wtyczce. Typ klucza zmienił się w rdzeniu. Oba zdania mogą być prawdziwe.
PHP potem trzyma numeryczne klucze stringowe jako liczby całkowite. Gdy "5292" idzie jako klucz tablicy w $wp_filter, PHP zostawia 5292. Po 7.1 closure podpięte do akcji ma klucz całkowity. Przed 7.1 każdy klucz był stringiem.
WP Rocket zakłada, że te klucze są stringami, z strict_types=1 w Cloudflare.php. Na init przechodzi callbacki na deleted_post i transition_post_status i woła substr() na każdym kluczu. Strict types odmawia koercji liczby całkowitej. Fatal.
Wordify opublikował pętlę:
foreach ( $original_wp_filter[ $priority ] as $key => $config ) {
if ( substr( $key, - strlen( $method ) ) !== $method ) {
Czysty WordPress plus WP Rocket często przeżywa. Austin Ginder to znalazł. Dodaj wtyczkę, która podpina closure na deleted_post z priorytetem 10, albo na transition_post_status z PHP_INT_MAX, i kolejne żądanie umiera. Elementor Pro to najpowszechniejszy przykład. Contact Form 7 Redirection to drugi. Druga wtyczka nie robi nic złego. Podpinanie closure to normalny WordPress.
W polskim sklepie WooCommerce ta druga wtyczka rzadko nazywa się „CF7 Redirection”. Częściej jest to Elementor Pro na stronie firmowej, Flexible Checkout Fields albo wtyczka do faktur VAT, która nasłuchuje zmiany statusu zamówienia. Mechanizm ten sam: closure na hooku, całkowity klucz, substr() w Cloudflare.php.
Matt Cromwell na X odnotował ironię: zmiana w rdzeniu była poprawką wydajności, a wydajność to produkt, który sprzedaje WP Rocket.
Sześciotygodniowy raport na GitHubie
wp-media/wp-rocket issue 8596 zgłoszono 6 lipca 2026, w czasie bety 7.1. Raport nazwał TypeError i zaproponował jednoliniowe rzutowanie na string. The Repository, 21 sierpnia: WP Rocket przejrzał zgłoszenie tego samego dnia, QA nie potrafiło go odtworzyć w testach automatycznych, i issue opadło. Nigdy nie dostało właściciela.
WordPress 7.1 wyszedł 19 sierpnia 2026, w zamykający dzień WordCamp US w Phoenix. Ginder napisał tego samego dnia: strony WP Rocket w parku Anchor Hosting poszły offline po podbiciu 7.1. Łatał wtyczkę ręcznie, żeby je podnieść.
Dwa kolejne issue na GitHubie, 8740 i 8741, wpadły dzień po premierze. WP Rocket opublikował komunikat: nie aktualizuj do 7.1, dopóki nie będzie poprawki, z artykułem wsparcia pod docs.wp-rocket.me/article/1927. Później 20 sierpnia wypuścili 3.23.2.2, jednoliniowe rzutowanie z lipcowego raportu. Wordify sprawdził poprawkę na tym samym błędzie fatalnym, który wcześniej odtworzył na 3.23.2.1.
Pull na GitHubie to wp-media/wp-rocket#8745.
Sześć tygodni między zgłoszeniem a łatą to nie „QA nie zdążyło”. To issue bez właściciela, które wróciło dopiero wtedy, gdy produkcja klientów leżała. Na retainerze utrzymaniowym ten kalendarz oznacza jedno: nie czekasz na tweet dostawcy. Bety i RC 7.1 idą na klon, zanim rdzeń wejdzie w autoaktualizację w nocy czasu CET.
Kogo to wyłożyło
Liczby Gindera z parku, 20 sierpnia: 124 z 332 produkcyjnych stron z WP Rocket padło, 37 procent. Każdy crash to WordPress 7.1 + PHP 8.x + Cloudflare.php.
Późniejszy post-mortem WP Rocket, opisany przez The Repository 27 sierpnia, oszacował około 27 procent bazy użytkowników jako narażonych i około 10 procent faktycznie trafionych. CEO Rémy Lamiot powiedział, że Elementor Pro, mimo bazy instalacji i mimo że był jednym ze spustów, nie był na liście zgodności, którą testowali. Lipcowy raport nie miał właściciela. „This cost real time and real trust,” napisał.
Te dwa procenty to nie ten sam pomiar. Ginder liczył zarządzany park, który już miał WP Rocket. WP Rocket liczył całą bazę, w tym strony, które w tamtym tygodniu w ogóle nie wzięły 7.1, i strony bez drugiej wtyczki. Cytuj oba. Nie uśredniaj.
Wordify: pierwsza strona klienta podbiła rdzeń o 01:55 UTC. Pierwszy fatal w logu trzy sekundy później. Support wyłączył wtyczkę. Około 35 minut od początku do końca, większość to diagnoza, bo nikt jeszcze nie złączył „7.1” z „WP Rocket”.
01:55 UTC to 03:55 CET. W polskim sklepie na cyber_Folks albo home.pl ten sam mechanizm wygląda inaczej niż u Wordify. Autoaktualizacja rdzenia leci w nocy. Rano właściciel otwiera kokpit, żeby wystawić fakturę VAT, i widzi biały ekran. Checkout dla gości może jeszcze serwować starą stronę z cache LiteSpeed albo nginx FastCGI, więc telefon od klienta spóźnia się o godzinę. Diagnostyka zaczyna się od logu PHP, nie od homepage.
Andrew Hoyer napisał, że ostrzegał zespół przed 7.1 i i tak obudził się z dziesiątkami padniętych stron. Jego linia: testuj alphę, betę i RC na własnym stosie, zamiast ufać dostawcy. Steve Jones zapytał, czy ludzie aktualizują produkcję w godzinę po majorze, bez rollbacku. Oba pytania to robota retainera utrzymaniowego. To nie jest spór o markę.
Bezpieczna kolejność
Jeśli strona jest jeszcze na WordPressie 7.0.x, a WP Rocket jest starszy niż 3.23.2.2:
- Sklonuj na staging.
- Zaktualizuj WP Rocket do 3.23.2.2 na stagingu. Potwierdź, że ładują się wp-admin i wylogowana strona główna.
- Dopiero potem weź WordPressa 7.1 na stagingu. Sprawdź logowanie, checkout jeśli jest WooCommerce, formularz, cron.
- Powtórz tę samą kolejność na produkcji: najpierw wtyczka, potem rdzeń.
Staging u nas to klon, nie podkatalog na produkcji. Na cyber_Folks i home.pl podkatalog na tym samym vhostcie dziedziczy object cache i ciasteczko sesji, więc test 7.1 miesza się z produkcją. Osobna instalacja, to samo PHP, ten sam Redis jeśli jest, ten sam zestaw wtyczek.
Jeśli autoaktualizacje już wzięły 7.1 i strona jest biała, pomiń spokojną ścieżkę. Najpierw wyłącz wtyczkę.
Nie włączaj z powrotem 3.23.2.1 na 7.1. Artykuł wsparcia WP Media jest jednoznaczny: jeśli w liście wtyczek nie widać aktualizacji, idź ich przewodnikiem o brakującej aktualizacji. Ponowne włączenie zepsutej wersji znowu kładzie stronę.
Bardzo stare buildy WP Rocket, sprzed pętli w Cloudflare.php, nie są dotknięte. Wordify dał pasmo od około 3.16 do 3.23.2.1. Jeśli nie jesteś pewien, i tak zaktualizuj do 3.23.2.2. To wersja z rzutowaniem na string.
| Element | Wersja / data | Rola |
|---|---|---|
| WordPress | 7.1 Mary Lou, 19 Aug 2026 | Zmienił ID hooków na spl_object_id (Trac 65919) |
| PHP | 8.x z strict_types=1 w pliku wtyczki | Całkowity klucz w substr() to TypeError, nie ostrzeżenie |
| WP Rocket | 3.16 do 3.23.2.1 | Cloudflare.php:562 chodzi po kluczach hooków na init |
| WP Rocket | 3.23.2.2, 20 Aug 2026 | Jednoliniowe rzutowanie na string z GitHub 8596 |
| Wtyczka wyzwalająca | Elementor Pro, CF7 Redirection, inne | Closure na deleted_post albo transition_post_status |
Co 7.1 naprawdę wpuściło i co wycięło, opisaliśmy w nocie o mapie drogowej WordPress 7.1. Edytor wpisów w iframe to osobne pęknięcie deweloperskie. Szczegóły w nocie o edytorze w iframe. Ten tekst dotyczy tylko fatalu Rocket.
Gdy wp-admin jest już biały
Nie kasuj Cloudflare.php. Wordify: klasa jest wpięta w kontener wtyczki, a usunięcie pliku zamienia ten fatal na inny.
WP-CLI. WP-CLI ładuje wtyczki, więc gołe wp plugin deactivate wp-rocket umiera. Pomiń wtyczkę, gdy ją wyłączasz:
wp plugin deactivate wp-rocket --skip-plugins=wp-rocket
SFTP. Zmień nazwę wp-content/plugins/wp-rocket na wp-rocket.off. WordPress traktuje przemianowany katalog jako wyłączony przy następnym żądaniu. Na cyber_Folks i home.pl to ten sam ruch przez FileZilla albo menedżer plików w panelu. Nie ruszaj wp-rocket w bazie opcji, dopóki katalog nie zmieni nazwy.
Potem zaktualizuj do 3.23.2.2 z wp-admin, który znowu żyje, i włącz wtyczkę.
Rollback do 7.0.4 z kopii sprzed aktualizacji też podnosi stronę. To wolniejsza ścieżka. Wyrzuca pliki 7.1, które już zapisałeś na dysk. Użyj jej, gdy nie masz SFTP ani WP-CLI.
Cache HTML na poziomie hosta (LiteSpeed, nginx FastCGI, cache HTML Cloudflare) może dalej serwować ostatnią dobrą stronę anonimowym gościom, podczas gdy wp-admin jest martwy. To chowa awarię przed częścią klientów i opóźnia zgłoszenie. Sprawdzaj log błędów, nie tylko homepage. W sklepie z fakturami VAT gość nadal widzi katalog, a redaktor nie wystawi dokumentu. To nie jest „strona działa”.
Jak testujemy podbicie rdzenia
WPPoland (Mariusz Szatkowski) traktuje majora jako trójwarstwowy test, nie jako pozycję w kalendarzu.
Staging jest klonem, nie podkatalogiem na produkcji. To samo PHP, ten sam object cache, te same wtyczki. Najpierw bierzemy aktualizacje wtyczek, które mają znaną niezgodność. Dla 7.1 ta lista zaczynała się od WP Rocket 3.23.2.2. Potem rdzeń. Potem lista dymna: logowanie, zapis w edytorze wpisów (teraz zawsze w iframe), koszyk i checkout WooCommerce jeśli sklep je ma, POST formularza, przebieg crona. Na sklepie z fakturami VAT dokładamy wystawienie dokumentu i zmianę statusu zamówienia, bo to właśnie transition_post_status i pokrewne hooki odpalały pętlę w Cloudflare.php.
Nie ufamy zdaniu „WP Rocket powiedziało, że testowali 7.1”. Testowali. Ich zestaw testów przegapił całkowity klucz plus closure z drugiej wtyczki. Czysta instalacja Gindera nie padła. Kombinacja padła. Kombinacja to to, czym naprawdę jest strona klienta.
Na produkcji trzymamy nazwaną kopię sprzed podbicia i 15-minutowe okno, w którym ktoś patrzy w log błędów, nie tylko w ping uptime. Biała strona główna z 200 z cache HTML to nie zaliczenie. Okno ustawiamy w CET, zwykle rano po nocnej autoaktualizacji, bo to wtedy polski sklep na cyber_Folks albo home.pl pierwszy raz ładuje kokpit.
Typowy klon klienta w tym warsztacie to WordPress + WooCommerce albo Elementor + WP Rocket + wtyczka formularza, często Flexible Checkout Fields albo wtyczka do KSeF i faktur VAT. To ta kombinacja, którą opisali Ginder i Wordify, tylko ze stosem, który tu naprawdę stoi. Nie czekamy na tweet dostawcy „przetestowaliśmy 7.1”. Bierzemy 7.1 na klonie, wołamy / i /wp-admin/, i grepujemy log PHP pod TypeError i Cloudflare.php. Jeśli log milczy, a oba URL-e zwracają 200 bez pomijania wtyczki, podbicie może iść na produkcję w tej samej kolejności.
Wersja PHP jest częścią klona. TypeError to pęknięcie strict types na PHP 8. Host, który jeszcze siedzi na PHP 7.4, tego konkretnego fatalu nie rzuci. To nie jest powód, żeby zostać na 7.4. To powód, żeby testować 8.2 albo 8.3 z tym samym zestawem wtyczek, który leci na produkcji, a nie z gołym WordPressem. Na cyber_Folks przełączenie wersji PHP na klonie jest w panelu. Na home.pl też. Test 7.1 na PHP 7.4 nic nie mówi o produkcji na 8.3.
To jest utrzymanie stron WordPress w jednym akapicie. Najpierw staging. Najpierw wtyczka, gdy dostawca ma pin. Potem rdzeń. Health check na końcu. Pisemna wycena po krótkim briefie, potem faktura VAT.
Jeśli publiczna warstwa już siedzi na Cloudflare Workers albo Pages, fatal PHP i tak zabija wp-admin i każdą trasę origin. Cache HTML na brzegu nie zastępuje wtyczki, która wywala fatal na init. Filar Cloudflare edge to warstwa dostarczania. Ten incydent to warstwa origin.
Autoaktualizacje i 7.1.1
Wordify ostrzegł, że autoaktualizacje 7.1 toczyły się w tym samym tygodniu. Strona, której nikt nie tknął, mogła z dnia na dzień przejść ze sprawnej w leżącą.
Adam Silverstein otworzył Trac 65920 20 sierpnia: workflow GitHub Actions do testowania top 100 wtyczek z katalogu przeciwko nieopublikowanemu WordPressowi. Szkic PR 13198, z kamieniem milowym na 7.2. W tickecie zaznaczył, że tego konkretnego incydentu i tak by nie złapał, bo WP Rocket jest płatny, a API katalogu obejmuje wtyczki darmowe. Ta sama klasa fatalu po zmianie typu nadal może trafić darmową wtyczkę z milionami instalacji. O to w tym workflow chodzi.
Aaron Jorbin wezwał wolontariuszy do prowadzenia 7.1.x. 7.1.1 było ołówkiem między 1 a 24 września 2026. Traktuj 7.1.1 tak samo: staging, potem produkcja. Jeśli 65919 dostanie w 7.1.1 warstwę zgodności dla całkowitych kluczy, to dodatkowe ubezpieczenie. To nie jest powód, żeby pominąć 3.23.2.2.
Jeffrey Paul poparł ticket Silversteina: powtarzające się fatale po majorach leżą w sferze odpowiedzialności rdzenia, nawet gdy zepsuty plik siedzi we wtyczce. To uczciwy podział. Rdzeń może testować wtyczki z katalogu. Rdzeń nie może testować płatnych wtyczek, których nie ma. Właściciel strony, albo osoba na retainerze, nadal ma klon.
Na retainerze nie wyłączamy autoaktualizacji „na zawsze”. Wyłączamy je na oknie majora, dopóki klon na cyber_Folks albo home.pl nie przejdzie listy dymnej. Potem autoaktualizacje wracają, z health checkiem po podbiciu, nie z wiarą że dostawca zdążył.
Czego nie twierdzimy
Nie mówimy, żeby wyrzucić WP Rocket. 3.23.2.2 to aktualny build z rzutowaniem. Wtyczki cache nadal zarabiają na siebie na originach PHP.
Nie mówimy, żeby pomijać WordPressa 7.1. Weszły responsywne style, media po stronie klienta, trwały pasek administratora i edytor w iframe. Nota o mapie drogowej wylicza, co weszło, a co nie.
Nie cytujemy cennika WP Rocket. Opłaty licencyjne firm trzecich to ich lista. Nasze utrzymanie wyceniamy indywidualnie, po briefie, na fakturze VAT.
Nie wymyślamy procentu dla „całego internetu”. 37 procent Gindera to park. 10 procent WP Rocket to ich szacunek własnej bazy. Oba są ze źródeł. Żadne nie jest spisem powszechnym.
Ostatnia aktualizacja 1 września 2026. Źródła: The Repository (21 i 27 sierpnia 2026), opis stosu u Wordify (20 sierpnia), issue 8596 i pull 8745 na GitHubie, Trac 65919 i 65920, changelog WP Rocket 3.23.2.2 i artykuł wsparcia 1927, Austin Ginder na X, cytaty z post-mortem Rémy’ego Lamiota za The Repository.







