More fixes

Action Scheduler: past-due actions found

Tools > Site Health shows "Action Scheduler: 1,204 past-due actions found; something may be wrong." Action Scheduler is the job queue WooCommerce and many plugins use for order emails, subscription renewals, stock updates, webhooks and Analytics imports. Past-due means those jobs are waiting and nothing is running them. It is almost always one of two things: the background runner never starts, or the jobs start and fail. Two checks tell you which.

Scheduled Actions screen

What the checks found


  

Check 1: does the runner ever start?

Open Tools > Scheduled Actions (on WooCommerce sites also under WooCommerce > Status > Scheduled Actions) and click Past-due. Note the oldest scheduled date. Wait five minutes, browse a couple of pages on the front of the site, then reload. If the count has not dropped and nothing moved to In-progress or Complete, the runner is not starting. The runner rides on WP-Cron, which only fires when someone visits the site and the site can call itself. Look in wp-config.php for define('DISABLE_WP_CRON', true);: if it is there, a real server cron job must replace it, and often it was never set up or stopped after a host move. Also check Site Health > Status for "could not complete a loopback request": a security plugin, password protection on the whole site, or a firewall rule blocking the site's own address stops every background job.

Check 2: do the jobs start and fail?

Still on Scheduled Actions, click Failed, and open the Log column of a few rows. Each failed job names its hook (for example woocommerce_run_product_attribute_lookup_update_callback or a subscription renewal) and the error it hit. A PHP fatal error, a timeout, or "action failed via async request" repeated on the same hook means one plugin's job is broken and keeps the queue busy. Hooks that belong to a plugin you have since deleted show "no callbacks are registered"; those can never run.

What each answer means

What you seeCauseFix
Nothing moves; DISABLE_WP_CRON is trueWP-Cron is switched off and no server cron replaces itAdd a server cron job in your hosting panel that requests https://yoursite.com/wp-cron.php?doing_wp_cron every 5 minutes, or runs wp cron event run --due-now
Nothing moves; Site Health shows a loopback errorThe site cannot call itself: security plugin, site-wide password, Cloudflare rule, or wrong DNS on the serverAllow requests from the server's own IP and to wp-cron.php and admin-ajax.php; see the loopback guide linked below
Queue only moves when you are logged inA quiet site with page caching: visitors get cached pages, so WP-Cron is rarely triggeredSet up a real server cron as above; it runs whether or not anyone visits
Thousands of failed rows on one hookOne plugin's job throws an error every timeRead the log message, update or fix that plugin, then rerun a few rows by hand with Run to confirm
"no callbacks are registered" on old hooksJobs left behind by a removed pluginSearch the hook name, select those pending rows and use Cancel; they will never run
Screen is very slow, table has millions of rowsCompleted and cancelled actions are not being cleaned up because the runner stallsFix the runner first; Action Scheduler then deletes finished actions older than 30 days on its own
Count drops, then jumps back dailyRunner works but is too slow for a busy shopRun the queue from server cron with wp action-scheduler run every few minutes instead of relying on page visits

Check it worked

After the fix, open Past-due again and reload every few minutes. The count should fall steadily and new rows should appear under Complete with recent dates. Place a test order or trigger the plugin's own job, and confirm its action completes within a few minutes. Then check Site Health again: the past-due warning clears once the backlog is worked through.

What not to do

If you would rather someone else finds why the queue is stuck and fixes it, that is what the box below is for. Related: REST API and loopback errors, scheduled posts not publishing, WooCommerce order emails not sending.