WooCommerceSubscriptionsUpdated for 2026

WooCommerce Subscriptions Not Renewing

IN
Reviewed by the Instant Nerds Team|Last updated: June 2026
Quick summary

Failed subscription renewals are the most expensive WooCommerce problem precisely because they fail silently. Nobody gets an error, the store looks healthy, and you only notice when recurring revenue drops or customers churn. The first thing to settle is where the chain broke. If no renewal order is even created, your scheduled actions are not running, usually WP-Cron blocked by low traffic or a CDN. If the order is created but not paid, the payment token is missing or the gateway declined the card. If the customer was charged but the subscription still shows unpaid, a webhook is blocked. This page separates each break point and gives the exact check and fix for it, plus the manual renewal path to keep collecting while you investigate.

Key facts at a glance

WooCommerce renewal failures in 2026

Last updated

How a renewal is supposed to fire
On the due date, WooCommerce Subscriptions uses Action Scheduler to create a renewal order and charge the saved card off-session through the gateway. Action Scheduler depends on WP-Cron to run on time.
Why renewals silently stop
WP-Cron is triggered by page loads. On a low-traffic store, or one where a CDN like Cloudflare blocks the internal request, the scheduler never fires, so renewal orders are never created. No charge is attempted, so no error appears anywhere.
The first diagnostic
WooCommerce then Status then Scheduled Actions. Search the subscription number. Renewal actions sitting in the past, especially more than a day old, mean the scheduler is not keeping up and a server cron job is the fix.
Order created but not charged
A missing payment token. Under the subscription Billing section, the pencil icon should show a saved Customer ID and Payment ID. Blank means there is no stored card to charge off-session, common after a gateway or plugin change.
Charged but still shows unpaid
A blocked gateway webhook. Stripe or PayPal confirms payment back to your store by webhook. If it is blocked, the money moves but the order never updates, so the subscription looks unpaid while the charge sits in the gateway dashboard.
The off-session subtlety
A renewal is an off-session payment, charged while the customer is away. The first subscription payment can require Strong Customer Authentication, the 3D Secure step, but recurring renewals are merchant-initiated and usually exempt, which is what lets them auto-charge. Exemptions are not guaranteed though. The bank can still demand authentication, variable or metered amounts require it every time, and a card not authenticated when first saved can fail off-session with an authentication-required error.

Source: the WooCommerce Subscriptions documentation on scheduled action errors, the complete guide to scheduled events, the common-issues and failed-payment-retry docs, the Action Scheduler FAQ, the Stripe Strong Customer Authentication guidance, and our hands-on store repairs. Get a quote in 60 seconds →

How WooCommerce renewals are supposed to work

A WooCommerce subscription renewal is a small chain of events, and a renewal fails when any one link breaks. On the renewal date, the WooCommerce Subscriptions extension uses a background job system called Action Scheduler to create a new renewal order, then charges the customer saved card through the payment gateway without the customer being present. That last part matters: the customer is off-session, away from your site, so the whole thing has to happen automatically using a stored payment token.

Action Scheduler does not run on a timer of its own. It leans on WP-Cron, the WordPress task scheduler, and WP-Cron is itself triggered by page loads rather than a true system clock. On a busy store this is invisible, because constant traffic keeps WP-Cron firing and the queue moving. On a quiet store, or one sitting behind a proxy that intercepts the internal request WP-Cron sends to itself, the trigger can fail to fire for hours or days. When that happens, the scheduled renewal never runs, the renewal order is never created, and no payment is ever attempted. Nothing errors, because nothing tried.

Even when the scheduler is healthy and the renewal order is created, the payment can still fail at the gateway: a missing or expired token, a declined card, a webhook that never confirms the charge, or an authentication step the bank insisted on. Each of those is a different fix. So the entire diagnosis comes down to finding the one link that broke: was the renewal order created at all, was it charged, and did the charge confirm back to the store.

The three break points, in order
  • No renewal order created: the scheduler did not run. WP-Cron or Action Scheduler problem.
  • Order created, not paid: the charge failed. Missing token, gateway without auto-renewal support, or a card decline.
  • Charged, but order still unpaid: the confirmation did not arrive. A blocked or unregistered gateway webhook.

Which symptom matches yours

Find the row that matches what you see. Each one points to a different break point in the renewal chain.

SymptomMost likely root cause
Subscriptions are active but the next payment date is in the past and no renewal order appearsScheduled actions are not running. WP-Cron is disabled or blocked, often by low traffic or a CDN like Cloudflare, so Action Scheduler never creates the renewal. The fix is a real server cron job.
A renewal order was created but it sits unpaid or pendingThe scheduler works but the charge did not. Usually a missing payment token, no saved Customer ID and Payment ID under Billing, or a gateway that only supports manual renewal.
The renewal order shows Failed with a gateway message in the order notesA card decline. Expired card, insufficient funds, or a bank declining the off-session charge. Read the exact reason in the order notes and enable the failed payment retry system.
The customer was charged at Stripe or PayPal but the subscription still shows unpaid or on holdA blocked or unregistered gateway webhook. The charge succeeded but the confirmation never reached your store, so the order never updated. Re-register the webhook and reconcile.
Renewals fail only for some customers, not allA payment-layer issue, not the scheduler. Specific expired cards, tokens lost in a gateway migration, or variable and metered amounts that require authentication every time. The shared factor across the failures is the cause.
You see many past-due actions more than a day old under Scheduled ActionsWP-Cron is not firing or Action Scheduler is blocked. Compare the WP-Cron time to the Action Scheduler time to tell which, then move to a server-level cron so the queue runs on a fixed interval.
Renewals stopped after a payment gateway change or plugin switchSaved payment tokens did not carry over. Customers need to re-add their cards, or the new gateway must be configured to import or re-tokenize the existing payment methods.

The five root causes

Renewal failures cluster into five causes, ordered along the renewal chain. Knowing which break point you are at is most of the fix.

1. Scheduled actions are not running

The renewal order is never created because the scheduler never fired. WooCommerce Subscriptions relies on Action Scheduler, and Action Scheduler relies on WP-Cron, which is triggered by page loads. On a low-traffic store the trigger fires too rarely, and behind a CDN or proxy like Cloudflare the internal loopback request WP-Cron sends to itself can be blocked entirely. The signature is subscriptions that are active with a next-payment date in the past and no renewal order to show for it. In WooCommerce then Status then Scheduled Actions you will see renewal actions piled up in the past. The durable fix is to stop depending on page-load triggering and run a real server-level cron job that calls the scheduler on a fixed interval.

2. A missing or invalid payment token

The renewal order is created but cannot be charged because there is no stored card to charge. An off-session renewal needs a saved payment token, shown in the subscription Billing section as a Customer ID and a Payment ID. When those are blank, WooCommerce has nothing to bill. This commonly follows a gateway change, a payment-plugin switch, a card that expired or was removed, or a migration where tokens did not carry across. The fix is to get a valid token back on the subscription, either by having the customer re-add their card through My Account then Payment Methods, or by configuring the gateway to re-tokenize existing customers.

3. A gateway that does not support automatic renewals

Not every payment gateway supports automatic recurring billing. Some can only take a manual payment, where the customer has to come back and pay each renewal order themselves. If your store is on one of those, the renewal order is created and then waits, unpaid, for a customer action that most customers never take. The signature is renewal orders consistently sitting in a pending state with no decline message, because no automatic charge was ever attempted. The fix is to move recurring subscriptions to a gateway that supports off-session tokenized billing, such as a properly configured Stripe or PayPal integration, or to accept that the store runs on manual renewals and build the customer prompts around that.

4. A card decline or an off-session authentication failure

Here the charge was attempted and the gateway said no. The renewal order shows as failed, and the Order Notes record the reason: an expired card, insufficient funds, a lost-or-stolen flag, or a bank that declined the off-session attempt. A specific variant is authentication. Recurring renewals are merchant-initiated and usually exempt from the Strong Customer Authentication step, but exemptions are not guaranteed, variable or metered amounts require authentication every time, and a card that was not properly authenticated when first saved can fail off-session with an authentication-required error. The fix is the failed payment retry system, which re-attempts the charge on a schedule and can prompt the customer to update or re-authenticate their card.

5. A blocked or unregistered gateway webhook

This is the confusing one, because the customer was actually charged. Stripe and PayPal confirm a payment back to your store through a webhook, a server-to-server message that tells WooCommerce the charge succeeded so it can mark the renewal order paid and extend the subscription. If the webhook endpoint is not registered, or a firewall or security plugin blocks it, the money moves at the gateway but the confirmation never lands. The order stays pending, the subscription can flip to on-hold, and the customer gets a dunning email for a payment they already made. You will see the successful charge in the gateway dashboard with no matching paid order in WooCommerce. The fix is to re-register the webhook endpoint, confirm it is reachable, and reconcile the affected orders.

DIY vs hand it off

Some renewal fixes are a settings check or a customer email. Others involve server cron, gateway webhooks, and token migrations on live recurring revenue. If the left column matches you can likely do this yourself. If the right column matches, get help before you risk the billing.

Realistic on your own

  • A single customer card expired and they can re-add it
  • You can read the Scheduled Actions screen and the order notes
  • You have server access to add a real cron job
  • You only need to manually process a few overdue renewals
  • The failed payment retry system just needs enabling
  • You have a staging site and a recent backup to test on

Hand it off, protect the revenue

  • Recurring revenue has been silently failing and you need a full reconcile
  • Customers were charged but orders show unpaid and webhooks are involved
  • You are migrating gateways and need to preserve saved tokens
  • Many subscriptions are overdue and need a careful batched catch-up
  • You cannot tell whether WP-Cron or Action Scheduler is the blocker
  • You are not comfortable editing wp-config and server crontab on production

How to diagnose it

Walk the renewal chain in order. The first two steps tell you which of the three break points you are at, and you can stop as soon as the cause is clear.

1
Check the subscription status and next payment date

Open the subscription under WooCommerce then Subscriptions. If it is Active but the next payment date is in the past, and there is no recent renewal order, the renewal never ran. That points at the scheduler, step two. If a renewal order exists but is unpaid or failed, skip to the payment checks.

2
Look at Scheduled Actions

Go to WooCommerce then Status then Scheduled Actions and search the subscription number. Renewal actions sitting in the past, especially several that are more than a day old, mean the scheduler is not keeping up. Check the Logs column for error messages on any failed actions.

3
Decide WP-Cron disabled vs Action Scheduler blocked

Compare the WP-Cron time to the Action Scheduler time. If the WP-Cron time is in the past, at or before the Action Scheduler time, WP-Cron is effectively disabled. If WP-Cron is recent, within minutes and after the Action Scheduler time, then Action Scheduler is blocked from processing. Either way the durable answer is a server cron.

4
Verify the payment token on the subscription

In the subscription Billing section, click the pencil icon and confirm there is a saved payment method with a Customer ID and a Payment ID. If those are blank, there is no card to charge off-session and the fix is to restore the token, not the scheduler.

5
Read the failed renewal order notes

Open the failed renewal order and read the Order Notes. The gateway records the exact reason there: an expired card, insufficient funds, a decline, or an authentication-required error. This single line usually identifies the fix.

6
Reconcile the gateway dashboard against your orders

If a customer says they were charged but the subscription shows unpaid, open the Stripe or PayPal dashboard and find the charge. A successful charge at the gateway with no matching paid order in WooCommerce means the webhook did not arrive. Check the gateway webhook settings and your firewall or security plugin.

How to fix it

Each branch stands alone. Pick the one your diagnosis pointed to. The manual renewal at the end keeps revenue flowing while you work.

If the scheduler is not running: set up a real server cron

Stop relying on the page-load trigger and run the WordPress scheduler from a true server cron job. First, disable the built-in trigger in wp-config.php:

// Stop WordPress from triggering WP-Cron on page loads
define( 'DISABLE_WP_CRON', true );

Then add a server cron job that runs the scheduler on a fixed interval. Use WP-CLI if available, which also processes Action Scheduler reliably, or call wp-cron.php directly. Hitting it on the server bypasses a CDN like Cloudflare that may block the loopback request.

# Run the WordPress scheduler every 5 minutes via WP-CLI
*/5 * * * * cd /var/www/yourstore && wp action-scheduler run >/dev/null 2>&1

# Or call wp-cron.php directly on the server, bypassing the CDN
*/5 * * * * curl -s "https://yourstore.com/wp-cron.php?doing_wp_cron" >/dev/null 2>&1

Once the scheduler is running, catch up the backlog with the manual renewal action below so overdue subscriptions are charged and brought current.

If the payment token is missing

The subscription has no card to charge. The reliable fix is to get the customer to re-add their payment method, which creates a fresh token. They can do this from My Account then Payment Methods, or by using the Change payment button on My Account then Subscriptions.

If the tokens were lost in a gateway migration, your new gateway may support importing or re-tokenizing existing customers from the old gateway. That avoids asking every customer to re-enter a card. Confirm whether your gateway offers a migration path before mass-emailing customers.

If the gateway does not support automatic renewals

Move recurring subscriptions to a gateway that supports off-session tokenized billing, such as a properly configured Stripe or PayPal integration. Confirm the gateway lists automatic recurring or subscription support, not just one-time payments, before switching.

If you cannot change gateways, accept that the store runs on manual renewals and build the experience around it: clear renewal-due emails with a direct pay link, and the failed payment retry system to keep prompting. Manual renewal is a viable model, it just needs the customer prompts that automatic billing does not.

If cards are declining or failing authentication

Enable the failed recurring payment retry system. It re-attempts a declined renewal on a schedule and emails the customer to update their card, which recovers revenue from temporary declines like insufficient funds. For authentication failures, make sure cards are authenticated at the time they are saved, so future off-session charges carry a valid authentication, and expect that variable or metered amounts will require the customer to authenticate each time.

If the customer was charged but the order shows unpaid

Fix the webhook. In your gateway dashboard, confirm the webhook endpoint for your store is registered and pointing at the correct URL, and check that no firewall rule or security plugin is blocking incoming requests to it. Send a test event from the gateway and confirm your store receives it. Then reconcile the affected orders: match each successful gateway charge to its WooCommerce order and mark the order paid so the subscription extends correctly and the customer stops getting dunning emails.

Keep collecting while you investigate. Open the subscription, and in the order Actions widget choose Create Pending Renewal Order, then Process renewal to charge the saved card now. This works for any subscription with a valid token and lets you clear a backlog of overdue renewals by hand.

Let us fix it in 2 hours →

A real renewal-failure debug session

A composite from the WooCommerce subscription repairs we run most weeks, with identifying details removed.

Scenario

A membership store noticed monthly recurring revenue had quietly dropped about 20 percent over two months. No errors, no support tickets, members still had access. The owner assumed churn. In fact, renewals had been failing to run at all. The store ran on a low-traffic plan behind Cloudflare, and many subscriptions were Active with a next-payment date weeks in the past.

Diagnosis

WooCommerce then Status then Scheduled Actions was full of past-due renewal actions, dozens of them more than a day old. Comparing the WP-Cron time to the Action Scheduler time showed WP-Cron was effectively never firing. The cause was the Cloudflare proxy intercepting the internal loopback request that WP-Cron depends on, so on a quiet store the scheduler simply never triggered. The payment tokens were intact, so once the scheduler ran, the cards would charge.

Resolution

We set DISABLE_WP_CRON in wp-config and added a server cron job running the scheduler every five minutes via WP-CLI, bypassing Cloudflare entirely. With the queue moving again, we worked through the backlog using Create Pending Renewal Order and Process renewal on each overdue subscription, charging the saved cards and bringing accounts current. We enabled the failed payment retry system to catch the handful of genuinely expired cards. Recurring revenue returned to its prior level within the day.

Total elapsed
Scheduler fixed and the overdue backlog charged inside the 2-hour window, after two months of silent revenue loss.

When to stop and hand it off

Four situations where DIY costs more than help. First, recurring revenue has been silently failing for weeks and you need a careful reconcile, matching gateway charges to orders without double-charging anyone. Second, customers were charged but their orders show unpaid, which means webhooks and a delicate reconciliation rather than a setting. Third, you are migrating payment gateways and need to preserve saved tokens so customers are not all forced to re-enter cards. Fourth, you cannot safely edit wp-config and the server crontab on production. We diagnose the exact break point, fix the scheduler with a proper server cron, repair webhooks and tokens, and catch up the overdue backlog without double-charging. Flat $49 to $149, done in two hours when scope fits, money back if we cannot.

Get a quote in 60 seconds

WooCommerce subscription renewal FAQ

My WooCommerce subscriptions are active but the next payment date is in the past and nothing is charging. Why?

This is the classic signature of scheduled actions not running. WooCommerce Subscriptions uses a background system called Action Scheduler to create the renewal order and charge the saved card on the due date, and Action Scheduler depends on WP-Cron to fire on time. WP-Cron is triggered by page loads, so on a low-traffic store, or one where a proxy like Cloudflare blocks the internal request, the scheduler never runs and renewals simply never happen. There is no error because the charge was never attempted. Check WooCommerce then Status then Scheduled Actions and search the subscription number. If you see renewal actions sitting in the past, especially more than a day old, your scheduler is not running and the fix is a real server-level cron job.

A renewal order was created but it was not paid. What went wrong?

When the renewal order exists but did not charge, the scheduler is working and the failure is at the payment step. The most common cause is a missing payment token. Open the subscription under WooCommerce then Subscriptions, look at the Billing section, click the pencil icon, and confirm there is a saved payment method with a Customer ID and a Payment ID. If those are blank, the store has no stored card to charge off-session, which commonly happens after a gateway change, a payment-plugin switch, or a card that was removed or expired. The other possibility is that the charge was attempted and declined. Open the failed renewal order and read the Order Notes, where the gateway records the exact reason, such as an expired card or insufficient funds.

How do I tell whether WP-Cron is disabled or Action Scheduler is just blocked?

WooCommerce documents a date comparison for this. Look at the WP-Cron time and the Action Scheduler time. If the WP-Cron time is in the past, at or before the Action Scheduler time, WP-Cron itself is effectively disabled and nothing is triggering the queue. If the WP-Cron time is recent, within the last few minutes and after the Action Scheduler time, then WP-Cron is firing but Action Scheduler is blocked from processing, usually by a server resource limit or a stalled queue. Either way, a pile of past-due actions more than a day old in WooCommerce then Status then Scheduled Actions confirms the queue is not keeping up, and the durable fix is a server cron job that runs the scheduler on a fixed interval instead of relying on visitor traffic.

I am behind Cloudflare and my renewals stopped. Is that related?

Very likely. WP-Cron works by the site sending an HTTP request to its own wp-cron.php on each page load. When a proxy or CDN like Cloudflare sits in front of the site, that internal loopback request can be intercepted or blocked, so WP-Cron never actually triggers even though pages are loading normally for visitors. The result is exactly what you are seeing: the store looks healthy, traffic is fine, but the subscription scheduler never fires and renewals quietly stop. The fix is to stop relying on the page-load trigger and run a real server cron job that calls the scheduler directly on the server or through WP-CLI, bypassing the proxy entirely.

Some subscriptions renew and some do not. Why is it inconsistent?

Inconsistent renewals usually point at the payment layer rather than the scheduler, because if the scheduler were dead, nothing would renew. The common patterns are per-customer: a specific customer card expired or was replaced, so their token no longer charges, while everyone else renews fine. A subset of customers whose cards were saved before a gateway migration lost their stored token in the move. Or a group of renewals with variable or metered amounts that require fresh authentication every time, unlike fixed-price renewals that are usually exempt. Open a few of the failing renewal orders, read the Order Notes for the gateway message, and check whether the failures share a gateway, a card vintage, or a variable price. The shared factor is the cause.

My customer was charged at Stripe but the subscription still shows unpaid. How?

This is a webhook problem. Gateways like Stripe and PayPal confirm a payment back to your store through a webhook, a server-to-server message that tells WooCommerce the charge succeeded so it can mark the renewal order paid and extend the subscription. If the webhook endpoint is not registered, or a firewall or security plugin blocks it, the money moves at the gateway but your store never hears about it, so the order stays pending and the subscription looks unpaid or goes on hold. You will see the successful charge in the Stripe or PayPal dashboard with no matching paid order on your side. The fix is to re-register the gateway webhook endpoint and confirm it is reachable, then reconcile the affected orders.

What does off-session payment mean and why do some renewals need authentication?

A renewal is an off-session payment, meaning the customer is not present on your site when it runs. The first subscription payment is customer-initiated and can require Strong Customer Authentication, the 3D Secure step, but the recurring renewals are merchant-initiated and are generally exempt from that step, which is what lets them charge automatically. The catch is that exemptions are not guaranteed. The customer bank can still demand authentication, and variable or metered amounts require it every time. If the card was not properly authenticated when it was first saved, the off-session charge can fail with an authentication-required error. The fix is to make sure cards are authenticated at save time, and to use the failed payment retry system so a customer can complete authentication when a renewal needs it.

How do I keep collecting money while I investigate the root cause?

WooCommerce gives you a manual renewal path so revenue does not stop while you fix the underlying issue. Open the subscription, and in the order Actions widget choose Create Pending Renewal Order, then choose Process renewal to charge the saved card immediately. This works for any subscription that has a valid payment token, and it lets you catch up a backlog of overdue renewals by hand. It is a stopgap, not a fix. If the scheduler is not running you will be doing this manually every cycle until the server cron is in place, and if the token is missing the manual charge will also fail, which itself tells you the problem is the token rather than the scheduler.

Sources and further reading

Every claim on this page traces back to the WooCommerce Subscriptions documentation, the Action Scheduler project, or the Stripe authentication guidance.

Why we fix subscription billing faster than a support ticket

2h

2-Hour Guarantee

Fixed in 2 hours or your money back. Every cycle of broken renewals is recurring revenue gone.

$49

Flat Rate $49 to $149

No hourly billing. We fix the scheduler, the tokens, and the webhooks the first time.

100%

Money-Back Guarantee

Cannot fix it? You do not pay. Zero risk to you.

Get your recurring revenue flowing again

We fix WooCommerce subscription renewals every week, from stuck schedulers to missing tokens to blocked webhooks. Flat $49 to $149, done in 2 hours when scope fits, money back if we cannot.

Fix My Renewals Now