{"id":19001591,"date":"2026-08-24T15:50:20","date_gmt":"2026-08-24T15:50:20","guid":{"rendered":"https:\/\/wordpress.org\/support\/topic\/purge-failure-in-version-2-4-4\/"},"modified":"2026-08-24T15:55:07","modified_gmt":"2026-08-24T15:55:07","slug":"purge-failure-in-version-2-4-4","status":"publish","type":"topic","link":"https:\/\/wordpress.org\/support\/topic\/purge-failure-in-version-2-4-4\/","title":{"rendered":"Purge failure in version 2.4.4"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I was able to reproduce and isolate the manual purge failure in version 2.4.4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Symptom<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Manual cache purge from the WordPress admin bar or plugin settings page fails with:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>The Hestia Nginx Cache could not be purged!<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The AJAX response from <code>\/wp-admin\/admin-ajax.php<\/code> is HTTP 200, but contains:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"success\": false,\n  \"data\": {\n    \"message\": \"The Hestia Nginx Cache could not be purged!\",\n    \"error\": \"Invalid nonce.\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Hestia API itself is working<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I verified the Hestia side independently.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>v-purge-nginx-cache<\/code> succeeds with exit code 0.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The configured access key also passes <code>v-check-access-key<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After verifying the API credentials, I called the plugin purge method directly through WP-CLI:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Hestia_Nginx_Cache::get_instance()-&gt;purge(true);\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP CODE: 200\nHESTIA EXIT CODE: 0\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Therefore the Hestia API request and the plugin&#8217;s actual purge method work correctly. The failure only occurs through the browser AJAX manual-purge path.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">PHP configuration was also checked:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PHP 8.4.24\nrequest_order: GP\nvariables_order: GPCS\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The AJAX request is not being cached and reaches WordPress normally.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Regression between 2.4.3 and 2.4.4<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The 2.4.4 &#8220;Fix all Plugin Check errors&#8221; change modified the nonce request field in <code>assets\/js\/admin.js<\/code> from:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>wp_nonce: nonce.textContent,\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>_wpnonce: nonce.textContent,\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">and changed the PHP validation in <code>includes\/admin.php<\/code> from the previous POST-based handling to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$query_arg = '_wpnonce';\n$valid_nonce = isset($_REQUEST&#091;$query_arg])\n    ? wp_verify_nonce(\n        $_REQUEST&#091;$query_arg],\n        'hestia-nginx-cache-purge-wp-nonce'\n    )\n    : false;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In my environment this consistently results in <code>Invalid nonce.<\/code> for the manual AJAX purge, while the direct purge method succeeds.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Patch tested<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I prepared a minimal compatibility patch.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The JavaScript request field is restored to the 2.4.3 name:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>wp_nonce: nonce.textContent,\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The PHP handler explicitly reads the POST value, unslashes and sanitizes it, while also accepting the 2.4.4 <code>_wpnonce<\/code> field as a fallback for cached JavaScript:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$nonce = '';\n\nif (isset($_POST&#091;'wp_nonce'])) {\n    $nonce = sanitize_text_field(wp_unslash($_POST&#091;'wp_nonce']));\n} elseif (isset($_POST&#091;'_wpnonce'])) {\n    $nonce = sanitize_text_field(wp_unslash($_POST&#091;'_wpnonce']));\n}\n\n$valid_nonce = $nonce !== ''\n    ? wp_verify_nonce(\n        $nonce,\n        'hestia-nginx-cache-purge-wp-nonce'\n    )\n    : false;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This does not remove or bypass nonce\/CSRF validation. It only restores the previously working POST field and handles the input explicitly in a Plugin Check-friendly way.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I also bumped the patched build to <code>2.4.4.1<\/code> so the plugin&#8217;s versioned <code>admin.js<\/code> URL changes and browsers do not keep the 2.4.4 JavaScript cached.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I can provide the complete patch\/diff if useful.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note: this finding specifically isolates the <strong>manual AJAX purge nonce failure<\/strong>. Automatic purge does not go through this AJAX nonce path and should be investigated separately if it is also failing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Download &#8220;2.4.4.1&#8221;: <a href=\"https:\/\/we.tl\/t-a1k1XjxH1gQTkccT\">https:\/\/we.tl\/t-a1k1XjxH1gQTkccT<\/a><\/p>\n","protected":false},"template":"","class_list":["post-19001591","topic","type-topic","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic\/19001591","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic"}],"about":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/types\/topic"}],"version-history":[{"count":1,"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic\/19001591\/revisions"}],"predecessor-version":[{"id":19001597,"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/topic\/19001591\/revisions\/19001597"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/support\/wp-json\/wp\/v2\/media?parent=19001591"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}