Fix: Stripe “You passed an empty string for ‘payment_method’” in WooCommerce (Payment Plugins)

If your Stripe checkout fails with “You passed an empty string for ‘payment_method’”, the browser never sent a valid payment method to Stripe. Most cases trace back to cached/optimized checkout pages, Stripe.js not loading, or a mode/key mismatch. Use the quick checks below, then the full step-by-step to permanently fix it.

 

Stripe for WooCommerce is throwing “You passed an empty string for ‘payment_method’”. How do I fix this?

Quick fixes (try these first)

  1. Bypass cache/optimization on checkout — exclude /cart/, /checkout/, /my-account/ and any URL containing ?wc-ajax=. Temporarily disable JS minify/deferral and combine to test.
  2. Hard refresh the checkout (clear CDN + site cache), then try again in a private window.
  3. Verify Stripe mode & keys — use Test keys in test mode and Live keys in live mode. Save settings.
  4. Check Stripe Dashboard > Developers > Logs — open the most recent payment_intent request and confirm it has a non-empty payment_method.

Why this error happens

When confirming a Payment Intent, Stripe expects a valid payment_method (for example, a PaymentMethod ID from the Payment Element). If the request sends an empty string or nothing at all, Stripe returns this error. Common causes: the Payment Element never initialized (script blocked or deferred), the checkout page was cached or combined/minified, or the site is mixing test and live keys so the client and server don’t agree.

Step-by-step: permanent fix

1) Update & sanity-check your setup

  • Update WordPress, WooCommerce, and Stripe for WooCommerce (Payment Plugins) to latest.
  • Confirm you’re using the intended checkout (Blocks or classic) and that a Stripe payment method is visible on the page.

2) Exclude checkout from caching, minify, and JS deferral

Add or confirm these exclusions in your caching/optimization tools (and purge the cache afterward):

  • Do not cache URLs: /cart/, /checkout/, /my-account/, any URL containing ?wc-ajax=
  • Never combine/defer/minify: https://js.stripe.com/v3 and your plugin’s Stripe assets (e.g. /wp-content/plugins/woo-stripe-payment/)

Example patterns you can paste into “Do not cache” or “Exclude JS” fields:

/cart/
/checkout/
/my-account/
\?wc-ajax=
https://js.stripe.com/v3
/wp-content/plugins/woo-stripe-payment/

3) Confirm Stripe mode & API keys

  • Open your Stripe plugin settings and verify:
    • Test mode ON → using Publishable key (test) + Secret key (test)
    • Live mode ON → using Publishable key (live) + Secret key (live)
  • Save settings and retest the checkout in the same mode shown on the settings page.

4) Verify the Payment Intent actually has a payment method

  1. Go to Stripe Dashboard > Developers > Logs.
  2. Open the recent /v1/payment_intents confirm call and check that payment_method is present (or that confirm was done with Elements on the client).
  3. If payment_method is missing/empty, the Payment Element likely failed to initialize. Re-check step 2 (no cache/minify/deferral) and that https://js.stripe.com/v3 loads on checkout.

5) Reproduce with all conflicts removed

  • Temporarily deactivate performance plugins (Autoptimize, LiteSpeed Cache, WP Rocket), page builders’ performance features, and any extra checkout or payment plugins. Keep just WooCommerce + Stripe.
  • Switch to a default theme (Twenty Twenty-Five) briefly and test. If the error disappears, re-enable items one by one to find the culprit.

6) (If using Apple Pay / Google Pay)

  • Ensure your domain is verified for Apple Pay in Stripe Dashboard and that Express buttons aren’t blocked by iframes or CSP rules.

7) Webhooks: recommended health check

  • In Stripe Dashboard > Developers > Webhooks, confirm your WooCommerce endpoint exists and events show as “Succeeded”. Misconfigured webhooks won’t usually cause an empty payment_method, but they help surface other flow issues.

Smoke tests you can run now

  1. Private window test: Open checkout in a private window with all optimizers disabled. If it works here, it’s a caching/optimizer issue.
  2. JS console: On the checkout page, open DevTools. Errors about stripe/Elements or blocked scripts indicate script loading conflicts.
  3. Stripe Logs A/B: Trigger two payments (one with optimizers off, one on) and compare the Payment Intent payloads for payment_method.

FAQ

Does mixed test/live mode cause this? Yes. If the front-end uses a publishable key from one mode and the server uses the other, Stripe can’t confirm with the PaymentMethod created by the browser.

Can Cloudflare or a CDN cause it? Yes, if it caches the checkout or modifies Stripe scripts. Bypass/disable on checkout and disable Rocket Loader/JS deferral for Stripe.

Do Checkout Blocks change anything? The fixes are the same: the Payment Element must load and submit. Make sure your Stripe block is present and no optimizer interferes.

Helpful links

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!