Every WordPress site administrator knows that feeling. You log into the dashboard, and there’s a message waiting for you: “A scheduled event has failed”. Your heart stops for a moment. Is the site down? Is it a serious crash?
Calm down! Before you start to panic, take a deep breath. This error, although it sounds serious, rarely means disaster. Most often, it’s simply a signal that the internal task scheduling mechanism in WordPress isn’t working optimally.
In this article, we’ll explain what this error is, why it appears, and how to fix it professionally in various server configurations.
What is WP-Cron?
WordPress needs to perform cyclical background tasks: publishing scheduled posts, creating backups, or scanning the site for viruses (as in the case of the wf_scan_monitor error from the Wordfence plugin). To handle these operations, it uses a built-in mechanism called WP-Cron.
The problem is that WP-Cron is not a real cron daemon known from Unix systems. It’s a “pseudo-cron” that has a fundamental flaw: it only runs when someone visits your website.
- On sites with low traffic: If no one visits the site, tasks aren’t performed on time, which leads to errors.
- On sites with high traffic: WP-Cron is called on every page load, which generates unnecessary server load.
In both cases, the solution is the same: disable the built-in WP-Cron and replace it with a stable, system-level cron job.
Scenario 1: A Single WordPress Site
This is the most basic and common configuration. The solution is simple and comes down to two steps.
Step 1: Disable the built-in WP-Cron mechanism
Edit the wp-config.php file in your site’s main directory and add the following line:
define(‘DISABLE_WP_CRON’, true);
Step 2: Configure a system cron
Log into your server via SSH and type crontab -e to edit the list of system tasks. Then, add one of the following lines, which will properly call the WordPress cron mechanism every 5 minutes.
- wget method: */5 * * * * wget -q -O – https://yourdomain.co.uk/wp-cron.php?doing_wp_cron >/dev/null 2>&1
- curl method: */5 * * * * curl https://yourdomain.co.uk/wp-cron.php?doing_wp_cron >/dev/null 2>&1
Remember to replace yourdomain.co.uk with your actual address. From now on, tasks will be executed regularly, regardless of site traffic.
Scenario 2: Multiple Sites on a Standard Server
If you manage multiple sites, adding a separate line in crontab for each one is impractical and difficult to maintain. A better solution is to create a single script that will automatically find all WordPress installations and run their tasks.
Step 1: Create the script file
Create a file, e.g., /usr/local/bin/run_all_wp_crons.sh, and paste the following content into it. The script searches the /var/www/ directory for wp-config.php files.
#!/bin/bash
#
# Script to run cron jobs for all WordPress sites
# Optimised for ISPConfig directory structure
# The main directory where the ACTUAL site files are located in ISPConfig
SITES_ROOT=”/var/www/clients/”
# Path to the PHP interpreter (may need to be adjusted)
PHP_EXECUTABLE=”/usr/bin/php”
# Logging (optional, but useful for debugging)
LOG_FILE=”/var/log/wp_cron_runner.log”
echo “Starting cron jobs (ISPConfig): $(date)” >> $LOG_FILE
# Find all wp-config.php files and run wp-cron.php for them
find “$SITES_ROOT” -name “wp-config.php” -print | while IFS= read -r -d ” config_file; do
# Extract the directory where WordPress is located
WP_DIR=$(dirname “$config_file”)
# Extract the user name (e.g., web4) from the path
# It’s the sixth element in the path /var/www/clients/client4/web4/web/
WP_USER=$(echo “$WP_DIR” | awk -F’/’ ‘{print $6}’)
if [ -z “$WP_USER” ]; then
echo “-> WARNING: Failed to determine user for: $WP_DIR” >> $LOG_FILE
continue
fi
# Check if the wp-cron.php file exists in this directory
if [ -f “$WP_DIR/wp-cron.php” ]; then
echo “-> Running cron for: $WP_DIR as user: $WP_USER” >> $LOG_FILE
# Run wp-cron.php using PHP CLI, switching to the correct user
su -s /bin/sh “$WP_USER” -c “(cd ‘$WP_DIR’ && ‘$PHP_EXECUTABLE’ wp-cron.php)”
else
echo “-> WARNING: Found wp-config, but no wp-cron.php in: $WP_DIR” >> $LOG_FILE
fi
done
echo “Finished: $(date)” >> $LOG_FILE
echo “—” >> $LOG_FILE
Step 2: Grant the script execution permissions
chmod +x /usr/local/bin/run_all_wp_crons.sh
Step 3: Create a single cron job to manage everything
Now your crontab can contain just one line:
*/5 * * * * /usr/local/bin/run_all_wp_crons.sh >/dev/null 2>&1
Scenario 3: Multiple Sites with ISPConfig Panel
The ISPConfig panel uses a specific directory structure with symlinks, e.g., /var/www/yourdomain.co.uk points to /var/www/clients/client1/web1/. Using the script above could cause tasks to be executed twice.
To avoid this, you need to modify the script to search only the target clients directory.
Step 1: Create a script optimised for ISPConfig
Create the file /usr/local/bin/run_ispconfig_crons.sh. Note the change in the SITES_ROOT variable.
#!/bin/bash
# Script to run cron jobs for all WordPress sites
# Optimised for ISPConfig directory structure
# We only search the directory with the actual site files
SITES_ROOT=”/var/www/clients/”
# Path to the PHP interpreter
PHP_EXECUTABLE=”/usr/bin/php”
# Optional log file to track progress
LOG_FILE=”/var/log/wp_cron_runner.log”
echo “Starting cron jobs (ISPConfig): $(date)” >> $LOG_FILE
find “$SITES_ROOT” -name “wp-config.php” -print0 | while IFS= read -r -d $’\0′ config_file; do
WP_DIR=$(dirname “$config_file”)
if [ -f “$WP_DIR/wp-cron.php” ]; then
echo “-> Running cron for: $WP_DIR” >> $LOG_FILE
(cd “$WP_DIR” && “$PHP_EXECUTABLE” wp-cron.php)
fi
done
echo “Finished: $(date)” >> $LOG_FILE
echo “—” >> $LOG_FILE
Steps 2 and 3 are analogous to Scenario 2: give the script execution permissions (chmod +x) and add a single line to crontab -e, pointing to the new script file.
Summary
The “A scheduled event has failed” error is not a reason to panic, but rather an invitation to improve your infrastructure. It’s a chance to move from the unreliable, built-in WordPress mechanism to a solid, professional system solution that guarantees stability and performance.
Regardless of your server configuration, you now have the tools to sleep soundly, knowing that your scheduled tasks are running like clockwork.