A WooCommerce scheduled sale ends only when a background task runs and puts the regular price back. If that task fails, never runs (WP-Cron turned off, a queue full of failed jobs), or a page cache keeps serving the old page, shoppers still see the sale price after the end date. Since WooCommerce 10.5 there is a second, confusing case: the sale does end, but the old sale price and dates stay saved in the product editor.
Why it happens
- The scheduled task didn’t run. Since WooCommerce 10.5, each product with sale dates gets its own Action Scheduler actions,
wc_product_start_scheduled_saleandwc_product_end_scheduled_sale(groupwoocommerce-sales), timed to the exact start and end. A daily action,woocommerce_scheduled_sales, runs around midnight store time as a safety net. Before 10.5 there was only the daily task. If none of them runs, the sale price stays. - WP-Cron is off. Action Scheduler is started by WP-Cron. If your
wp-config.phphasdefine( 'DISABLE_WP_CRON', true );and nothing on the server replaces it, or your store gets very few visits, actions pile up as “Past-due”. - The task fails. In an early 2026 thread on the WooCommerce forum, the store had more than 13,000 failed actions, and the sale task stopped after 300 seconds, which looked like a timeout. Running it by hand said “complete”, but the prices didn’t change.
- The products were changed outside the product editor. A GitHub comment from March 2026 notes that the per-product actions are created when a product is saved the normal way. Importers or custom code that write the database directly may leave the product waiting for the daily safety net, which can be up to a day late.
- A cache serves the old page. A page cache (WP Super Cache, your host’s cache, Cloudflare) can show the sale price until the cache is cleared, even when the product is already right.
- Lists and filters are out of date. In WooCommerce 10.5 to 10.7, the product page was right but the “On sale” block, price filters and price sorting could still show expired sales, because the product lookup table wasn’t refreshed. WooCommerce fixed it in 10.8.0.
- The sale ended, but the data stayed. In recent versions, when a sale ends WooCommerce only resets the active price. The sale price and the “From… To…” dates stay in the editor. A June 2026 feature request on woocommerce.com (on 10.8.1) asks for them to be cleared again, as they used to be.
How to check it yourself
- Look at the product as a shopper. Open the product in a private window. If you see the regular price with no “Sale!” badge, the sale ended; any sale price left in the editor is leftover data. If you see the discount, carry on.
- Open the scheduled actions. Go to WooCommerce > Status > Scheduled Actions. Search for
woocommerce_scheduled_salesand forwc_product_end_scheduled_sale. Check the Pending, Past-due and Failed tabs. - Read the log of a failed action. Click the action to see its log. A timeout or a “class not found” error points to a server limit or to WooCommerce files that didn’t update properly.
- Check the cron. In WooCommerce > Status, look at the Action Scheduler section of the report for past-due counts. Ask your host whether WP-Cron is disabled and, if so, whether a server cron replaces it.
- Rule out the cache. Clear your page cache and your CDN cache, then reload the product.
- Check your WooCommerce version. On 10.5 to 10.7 with problems only in the shop lists, filters or the On sale block, updating to 10.8 or later is the fix.
How to fix it
- Make a backup, and test on a staging copy if the store is large.
- Run the task. In Scheduled Actions, hover over the pending
woocommerce_scheduled_salesaction and click Run. Do the same for any pendingwc_product_end_scheduled_saleof the affected products. With WP-CLI you can runwp action-scheduler run. - Clean up failed actions. If thousands of failed actions come from a plugin you deleted, removing them makes the queue lighter. Ask your host or developer to raise the PHP time limit if the logs show timeouts.
- Make the cron reliable. If WP-Cron is disabled, set a server cron job that calls
wp-cron.phpevery 5 minutes (your host’s panel usually has a “Cron jobs” section), or ask your host to do it. - End the sale by hand. Edit the product, empty Sale price, click Cancel next to the sale dates (or delete them), and click Update. For a variable product, open Product data > Variations and do the same in each variation. Saving through the editor lets WooCommerce recalculate the price and its caches.
- Many products? Export the products from Products > Export, clear the sale price and sale date columns, and import the file with “Update existing products” checked. Try it with one or two products first. A bulk editor works too (ours is BulkPilot).
- Clear the caches again and check the product, the shop page and the On sale block.
- Update WooCommerce to 10.8 or later if the shop lists still show the expired sale.
How to stop it from happening again
Check Scheduled Actions once a week and keep a real cron running. If you want someone else to watch it, Melopo Radar checks every product in each sync and warns you with “Expired sale still visible” when the end date has passed and the product is still being charged at the sale price. If the sale ended correctly and only the old sale price and dates were left saved, it stays quiet: it compares against the price that is actually charged. From the same warning you can remove the sale with one click, for one product or in bulk; Radar clears the sale price through WooCommerce, so the price is recalculated. Be aware of its limits: Radar doesn’t read the scheduled actions, doesn’t repair your cron or failed tasks, doesn’t clear the sale dates, and looks at the product’s price, not at each variation. Radar has a free plan for one store and a 14-day Pro trial without a card.
FAQ
What time does a WooCommerce sale end? The editor treats the end date as the end of that day, 23:59:59 in your store’s time zone. Since WooCommerce 10.5 an action is scheduled for that moment; if it doesn’t run, the daily safety net around midnight should catch it.
Why does the editor still show the sale price after the sale ended? In recent versions WooCommerce resets the active price but keeps the sale price and dates saved. If the shop shows the regular price, the sale did end. You can delete the old values by hand.
Does it matter if WP-Cron is disabled? Yes. Action Scheduler needs WP-Cron or a server cron to start. Without either, sales don’t start or end on time.
Why do variable products fail more often? Each variation has its own sale price and dates, and the parent product shows a price range built from them. If one variation isn’t updated, the range still shows the sale.
Will clearing the cache end the sale? Only if the product was already right and the cache was showing an old page. If the sale price is still active in WooCommerce, you have to run the task or remove the sale.


