More fixes

WordPress scheduled posts not publishing ("Missed schedule")

You set a post, an offer or an event page to go live at 9am. At noon it is still not on the site, and the Posts list says Missed schedule in red. WordPress has no clock of its own: it checks for due posts only when someone loads a page and the site can then call itself back. Anything that stops that call (a setting copied over in a host move, a security rule, a cache that answers every visit, a quiet site) leaves the post waiting. Below is a rebuilt example (not a real client), how to find which cause you have, and the fix for each.

Posts > All Posts, Friday 11:40

What the checks found


  

First: get the post out, then find the cause

  1. Publish it by hand now. Open the post, set the date to now (or click Publish), and save. The post is live; the cause is still there for the next one.
  2. Read Site Health. Tools > Site Health. Two lines matter here: A scheduled event has failed or A scheduled event is late, and Your site could not complete a loopback request. The second one means the site cannot call itself, which is how the scheduler starts (the third and fourth rows below).
  3. Look at the queue. The free WP Crontrol plugin (Tools > Cron Events) lists every waiting job. If publish_future_post entries sit there hours past their time, the scheduler is not running at all. A note at the top saying DISABLE_WP_CRON is set is the first row below.

The causes and their fixes

CauseHow to spot itWhat to do
The built-in scheduler was switched off, and nothing replaced itdefine('DISABLE_WP_CRON', true); in wp-config.php. Common after a move to a new host or a speed-up guide: the line was copied, the server job it relies on was not. Every scheduled job stops, not just posts (backups, reminder emails, sitemap updates)Either remove the line, or keep it and add a real server job (next section). The second is better on a busy or cached site
A quiet sitePosts go out late rather than never: they appear when the first visitor of the day arrives. Overnight and early-morning times are hit mostA server job that runs the scheduler every 5 to 15 minutes, whatever the traffic (next section)
The site cannot call itself (loopback blocked)Site Health reports the loopback failure, often with a 401, 403 or timeout. Causes: a security plugin or host firewall blocking wp-cron.php, a password on the whole site (staging or "coming soon" protection), or the server unable to reach its own domain after a DNS or SSL changeAllow wp-cron.php in the security plugin's or host's firewall rules; take the site-wide password off a live site; ask the host to let the server reach its own domain. Or skip the loopback entirely with a server job
The cache answers every visitPage cache or a CDN (Cloudflare "Cache Everything", a host's built-in cache) serves pages without running WordPress, so visits never start the scheduler. Posts go out only when someone logs in or the cache expiresA server job, so the scheduler no longer depends on visits. Also clear the cache after a scheduled post goes out, or the home page keeps showing the old list (see changes not showing)
The time zone is wrongSettings > General shows a "UTC+0" style offset or a city in another country. The post went out, just hours early or late, and summer-time changes shift it againPick your own city (not a UTC offset) in Settings > General > Timezone, so daylight-saving changes are handled for you, then re-save the waiting posts
A plugin conflict or a fatal error in a jobWP Crontrol shows jobs running, but one keeps failing; the PHP error log names a plugin. Social auto-share and backup plugins are the usual suspects, because the scheduler runs their jobs in the same passRun the waiting job by hand from WP Crontrol and read the error; update or replace the plugin it names. More in the plugin conflict guide

The real fix for most sites: a server job

Most hosts' control panels have a "Cron Jobs" page (cPanel, Plesk, SiteGround Site Tools, Hostinger hPanel). Add a job that runs every 5 to 15 minutes with this command, using your own address:

wget -q -O - "https://example.com/wp-cron.php?doing_wp_cron" >/dev/null 2>&1

Then add (or keep) this line in wp-config.php, above the line that says "That's all, stop editing", so page visits stop starting the scheduler a second time:

define('DISABLE_WP_CRON', true);

If the host has no cron page, a free external service that requests the same address every 10 minutes does the same job. Managed WordPress hosts (WP Engine, Kinsta and similar) usually run this for you; check their docs before adding your own.

What not to do

For most sites this is one wp-config line and one cron job, about ten minutes' work once you know which cause it is. If you would rather hand it over, that is what the box below is for. Related: changes not showing, a plugin conflict, and site emails not arriving.