WooCommerce: “Sorry, your session has expired. Return to shop.” – How to Fix It

Quick answer: This WooCommerce error appears when the session/cookie check or a security nonce fails, most often because a cache/CDN is serving an old page or blocking WooCommerce’s dynamic requests. Fix it by bypassing cache on cart/checkout/account pages and WooCommerce cookies/endpoints, confirming your site URLs (www/HTTPS) match, and ensuring browser cookies are set.

Use the checklist and copy-paste rules below for common hosts, Cloudflare, WP Rocket, LiteSpeed, W3TC, and Nginx/Apache.

WooCommerce keeps showing “Sorry, your session has expired. Return to shop.” when I add to cart or hit checkout. How do I fix this? I’m using a cache/CDN.

Why this happens

WooCommerce relies on several first-party cookies (e.g., wp_woocommerce_session_*, woocommerce_cart_hash, woocommerce_items_in_cart) and dynamic endpoints (for example, ?wc-ajax=*) to keep carts and nonces in sync. If a page is cached when those values change or if cookies are ignored, WooCommerce treats the request as stale and throws “session expired.”

Fix checklist (start here)

  1. Open a private window and test again. If it works, your browser cache/cookies were the issue. Clear site cookies and try again.
  2. Bypass cache on:
    • URLs: /cart/, /checkout/, /my-account/, /add-to-cart/*, order-pay/received pages.
    • Query strings: add-to-cart, wc-ajax=* (e.g., get_refreshed_fragments, add_to_cart).
    • Cookies: if any of woocommerce_items_in_cart, woocommerce_cart_hash, or wp_woocommerce_session_* are present, bypass/disable cache for that request.
  3. Confirm cookies exist: in your browser devtools → Application/Storage → Cookies, you should see wp_woocommerce_session_* on your domain.
  4. Make your URLs consistent: match WordPress Address and Site Address (HTTPS vs HTTP, and www vs non-www). Mixed domains cause cookie mismatches.
  5. Do not set COOKIE_DOMAIN in wp-config.php: remove it if you find it. Let WordPress handle cookie scope automatically.
  6. Temporarily disable/minify exclusions: turn off JS/CSS combine/minify or defer on checkout/cart to rule out script-order issues.
  7. Retest with all non-essential plugins off (keep WooCommerce and your cache/CDN active) to check for conflicts; then re-enable one by one.

Copy-paste cache/CDN rules

Use these examples as a starting point and adapt paths to your setup.

Nginx (bypass cache for WooCommerce)

set $skip_cache 0;

# Bypass cache if WooCommerce cookies are present
if ($http_cookie ~* "wp_woocommerce_session_|woocommerce_cart_hash|woocommerce_items_in_cart") {
    set $skip_cache 1;
}

# Bypass cache on key endpoints/pages
if ($request_uri ~* "(?:/cart/|/checkout/|/my-account/|/addons/|/wc-api/|/order-pay/|/order-received/)") {
    set $skip_cache 1;
}
if ($arg_wc-ajax) { set $skip_cache 1; }
if ($arg_add-to-cart) { set $skip_cache 1; }

# Example fastcgi/proxy cache conditions
location / {
    # your usual config...
    if ($skip_cache = 1) {
        add_header X-Bypass-Reason "WooCommerce dynamic request";
        # don't use cache here (fastcgi_no_cache/proxy_no_cache/etc.)
    }
}

Apache/.htaccess (send no-store for sensitive pages)

<IfModule mod_headers.c>
  <FilesMatch "(cart|checkout|my-account|order-pay|order-received)">
    Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0"
  </FilesMatch>
</IfModule>

Cloudflare (Cache Rules)

  1. Create a Cache Rule → Bypass for URLs matching: *example.com/cart/*, *example.com/checkout/*, *example.com/my-account/*, plus Query String contains wc-ajax= or add-to-cart.
  2. If available, add a Bypass cache on cookie condition when cookies include wp_woocommerce_session_ or woocommerce_items_in_cart.
  3. Disable features that reorder scripts on checkout (e.g., Rocket Loader).

WP Rocket

  • WP Rocket already excludes common WooCommerce pages. Double-check Advanced Rules → Never Cache URLs includes /cart/, /checkout/, /my-account/.
  • Under File Optimization, temporarily disable Combine/Minify/Delay for JS/CSS while testing checkout.

LiteSpeed Cache

  • Cache → Cache Rules → Do Not Cache URIs: add /cart/, /checkout/, /my-account/.
  • Disable “Cache Login Page” and set “Cache REST API” to off during testing. Ensure “Guest Mode/Guest Optimization” isn’t caching checkout.

W3 Total Cache / SiteGround Optimizer / Others

  • Add the same URL and query string exclusions, and configure don’t cache when cookie present for WooCommerce cookies.

Diagnostics (if it still fails)

  1. Check cookies live: Open devtools → Network tab → pick the failed request; look for Cookie: header containing wp_woocommerce_session_*. If missing, a CDN/proxy is stripping cookies. Adjust its settings.
  2. Mixed domain/HTTPS: If you switch between www and non-www, or HTTP and HTTPS, the browser will not send the session cookie. Fix the canonical domain and set redirects accordingly.
  3. Server clock drift: Large time drift can make nonces appear expired. Ensure the server syncs with NTP.
  4. Regenerate permalinks: Settings → Permalinks → Save to refresh rewrite rules.

FAQ

Can I extend the lifetime of WooCommerce nonces?
You can filter nonce lifetimes in WordPress, but it’s better to resolve cache/cookie issues so fresh, uncached pages are served to shoppers.

What exactly should never be cached?
Cart, checkout, account pages; WooCommerce AJAX endpoints (any request containing wc-ajax=); and any request that includes WooCommerce session/cart cookies.

Summary

“Session expired” almost always traces back to cache or cookie handling. Bypass cache for WooCommerce’s dynamic pages, respect WooCommerce cookies, keep URLs consistent, and verify cookies are present on live requests. Once those are in place, the error disappears.

Need human WordPress help?

WP Assistant is a free tool created by Atiba Software, a WordPress design and development company located in Nashville, TN. If you need more personalized WordPress assistance let us know, and we’ll get back to you ASAP!