Fix “Invalid nonce” / “Nonce verification failed” in WordPress

Seeing “Invalid nonce” or “Nonce verification failed” when submitting a form, uploading media, or checking out? This usually means the page served an expired or mismatched security token due to caching, authentication, or route issues. Use the checklist below to refresh tokens, bypass caches for dynamic pages, and verify the request is sent with the correct headers.

I’m getting “Invalid nonce” / “Nonce verification failed” on WordPress. How do I fix it?

Work through these in order. Most sites recover by steps 1–3.

1) Purge cache and exclude dynamic pages

  • Purge all caches: page cache, object cache, CDN.
  • Exclude pages carrying nonces (forms, login, account, checkout, cart, admin screens) from caching. If your cache/CDN supports it, use ESI/fragment caching for nonce fragments.
  • Why: a cached page can serve a stale nonce to multiple visitors, triggering “invalid nonce” on submit.

2) Reproduce with all layers off

  • Temporarily disable security/WAF rules and optimization features (combine/minify/deferral) that touch admin-ajax.php or /wp-json/.
  • Retest logged-in and logged-out in a private window.

3) Verify the request actually sends a nonce

Open your browser DevTools → Network. Submit the form and check the request:

  • wp-admin/admin-ajax.php requests should include a nonce field (e.g., _wpnonce) in POST data.
  • REST requests must carry X-WP-Nonce (or _wpnonce) for authenticated actions.
# Example REST call with a nonce header
curl -i -X POST https://example.com/wp-json/your-namespace/v1/action \
  -H "X-WP-Nonce: <nonce>" \
  -H "Content-Type: application/json" \
  --data '{"ok":true}'

4) Confirm cookies, domain, and scheme

  • Ensure you’re consistently using either www or non‑www and the same protocol (HTTPS). Mixed domains/schemes can drop auth cookies and fail nonce checks.
  • Reverse proxies/CDNs should pass cookies to the origin for pages that require login or nonce verification.

5) Quick server checks

  • Permalinks: go to Settings → Permalinks and click Save (flush rules).
  • Time drift: verify server time (drastically wrong server clock can cause odd auth failures).
  • Error logs: look for fatals around form handlers or rest_api_init.

6) WooCommerce/checkout specifics

  • Bypass cache for Cart, Checkout, My Account, and any AJAX endpoints (e.g., ?wc-ajax=*).
  • Temporarily disable third‑party checkout customizers; re‑test. Then re‑enable one by one.

7) For developers: generate & verify nonces correctly

Classic form (admin-ajax):

// Output form field
wp_nonce_field( 'my_action', 'my_nonce' );

// Verify on submit
if ( ! isset( $_POST['my_nonce'] ) || ! wp_verify_nonce( $_POST['my_nonce'], 'my_action' ) ) {
  wp_send_json_error( 'Invalid nonce' );
}

REST request (cookie auth): enqueue a script with a localized nonce, then send it via X-WP-Nonce. See REST auth docs for details.

8) (Advanced) Adjust nonce lifetime, temporary mitigation

Default nonce lifetime is about a day. If users keep a form open for many hours, you can extend lifetime temporarily (security trade‑off!):

add_filter( 'nonce_life', function( $l ) { return 2 * DAY_IN_SECONDS; } );

Prefer a UX fix (auto-refresh nonce before submit) over a permanent lifetime increase.

Troubleshooting checklist

  • Dynamic pages excluded from cache; CDN/WAF not stripping cookies.
  • Request includes _wpnonce or X-WP-Nonce and matches the correct action.
  • Single canonical domain/protocol; logged-in cookies present on submit.
  • No plugin conflicts; errors clean in logs.

If you’re still stuck, capture a failing request (headers + response) and we can pinpoint whether it’s a stale page, missing header, or server block.

WooCommerce checkout shows “Invalid nonce”. Any WooCommerce-specific tips?

Yes, checkout pages are sensitive to caching and mixed domains.

  1. Exclude Cart, Checkout, My Account, and ?wc-ajax=* from all caches/CDNs.
  2. Disable third‑party checkout add‑ons and your theme’s checkout overrides; re‑enable one by one.
  3. Confirm your checkout runs on the same domain/protocol as the main site and that cookies are not stripped by a proxy.
  4. Re‑save permalinks and clear all caches before re‑testing.

If the error persists only with a specific gateway, test with it disabled to confirm, then contact that gateway’s support.