Read the error at the correct level
In the PHP log, WordPress writes Cron reschedule event error, followed by a task name, the code invalid_schedule and the message Event schedule does not exist. A forum thread describes this signal for wsal_generate_reports_cron, with the tenminutes recurrence and a stored interval of 600 seconds. This signal calls for a specific check: WordPress can reach a due task and fail while registering its next run. The log time does not say whether this occurrence's business processing succeeded, and the thread does not establish the same cause for every plugin version.
Separate three elements. The hook identifies the action to call, such as report generation. The recurrence key names the cadence, such as tenminutes. The interval is a duration in seconds. The queue may still contain an old event's name and interval while the code registering the recurrence no longer loads. Core may reread the stored interval during rescheduling; the function registering the next due time must still recognize the key. Seeing interval: 600 in the log therefore does not demonstrate that the recurrence is available.
Do not treat every scheduling error alike. could_not_set calls for investigating queue writes. An internal-call failure concerns triggering. Here, the message says rescheduling of this task was attempted. If different tasks never start and this trace is absent, use general WP-Cron diagnosis. If just one task fails with invalid_schedule while others continue, start with the key and its owner.
- Record the hook, recurrence key, log date with time zone and, if known, the date of the last business result. Do not copy event arguments into a shared channel.
- Look for the same error around two due times. An isolated trace during an update may not recur; a verified next occurrence gives a better indication.
- Choose an independent control, such as a staging task that creates a trace without sending email. It will verify that the runner works while you correct the targeted recurrence.
Check ownership through the dashboard and logs
This route suits someone managing WordPress with access to hosting logs but no terminal. In the dashboard, open Plugins > Installed Plugins. Record the version and status of the plugin providing the function named in the log. Also check whether it is network-managed. A hook name is a clue; confirm ownership in the publisher's documentation or with the code maintainer, especially if an in-house plugin uses a generic name. Randomly deactivating plugins is unnecessary to establish this connection.
On an isolated copy, use the plugin screen configuring the feature associated with this task. Record the old cadence and intended output. For a report generator, replace the recipient with a test inbox where possible and prevent external output from the copy. If the publisher documents a fix applicable to your version, install it on the copy. If the publisher says saving periodicity recreates the event, use that button once. Some screens save a preference without recreating an event: do not interpret form success as a queue test.
If you have neither log access nor a way to verify a result, give the task name, plugin version and time window to the hosting owner. Provide a precise check: find the exact code for this hook, then verify whether a next occurrence appears after execution. Site Health can help identify a broader problem; it does not enumerate recurrences actually loaded by this processing. When a plugin provides its own execution screen, distinguish its business history from native WP-Cron events.
- In staging, record the existing setting. Apply only the documented update or correction for the identified task. If the feature was deliberately removed, do not reactivate it merely to eliminate a log line.
- Wait for the runner's next normal pass and check for the test result. Check the following pass: one successful execution may correspond to the old event still present.
- If the trace repeats, return to the previous configuration on the copy and check the registry. If you replaced a setting, record its previous value and how to restore it. Avoid a full database restore on a site whose data continues changing.
Check the recurrence and event through WP-CLI
With authorized SSH access, you can read the recurrence registry and queue separately. Choose the staging WordPress folder and URL; in multisite, the URL selects the subsite. Do not add --skip-plugins to simplify the command: you could remove the very component supplying the frequency from diagnosis. The first result should show whether the sought key exists and its advertised interval. The second should show whether an occurrence of this hook carries the same key and when it is due in UTC.
The example targets the hook and key mentioned in the forum. Replace the path, URL and hook with your values. Neither command runs events or displays arguments. Several rows with the same hook may represent distinct tasks: if so, do not conclude they are duplicates. A row without recurrence may be an intentional one-time event; periodic rescheduling concerns events carrying a frequency. If no row remains, the queue may have lost the occurrence after the last pass, or the plugin may have removed it deliberately.
If the key exists in WP-CLI but the HTTP worker log says otherwise, compare contexts. A filter may load only on an administration page, behind a capability check or in a terminal-specific branch. A successful command does not prove that wp-cron.php has the same configuration. Also check whether both access routes use the same installation and code version. If the problem belongs to a third-party plugin, do not add a frequency under its name merely to silence it: record the mismatch, check the official fix and let the owner decide the frequency and processing.
An additional check helps in multisite: ask which domain the pass runs for and compare that subsite's queue with the one where the task was created. A key present in a healthy subsite's recurrences proves nothing for the subsite reporting the error if activation or settings differ. Record separately “key seen in terminal”, “key loaded by worker” and “new occurrence registered”. If you maintain the code, you can add a staging trace reporting only context and key presence, then remove it at the end. This result avoids changing the host's scheduler when the issue is a loading condition.
wp --path="/chemin/recette" --url="https://recette.example.test" cron schedule list --fields=name,interval
wp --path="/chemin/recette" --url="https://recette.example.test" cron event list --hook=wsal_generate_reports_cron --fields=hook,schedule,interval,next_run_gmtTry a recurrence whose code you control
Use this approach if you maintain the plugin or must prove in staging that the same runner can chain two occurrences of a task with a custom interval. The code registers a ten-minute recurrence and a control action writing one line to the PHP log. It schedules nothing by itself, sends no reports and does not affect the forum task. The useful point is filter placement: at initialization of the plugin file, outside a settings page and before calls using its recurrence.
On the copy, create wp-content/plugins/atelier-temoin-cron/atelier-temoin-cron.php in this installation's plugins folder and paste the code. Activate “Atelier — témoin de récurrence” under Plugins > Installed Plugins. Confirm that atelier_toutes_les_dix_minutes appears with 600 seconds in the WP-CLI list. Once, using the same targeting parameters as above, run wp cron event schedule atelier_recette_temoin '+2 minutes' atelier_toutes_les_dix_minutes. Check that the list filtered for atelier_recette_temoin shows a first due time and the expected interval. For this test, let the staging environment's usual runner perform the pass: manual execution does not demonstrate that the worker loads the filter.
Generally, a task scheduled for a given time does not necessarily execute to the second: account for runner frequency. Use staging with a known cadence. If the control never starts, check triggering before blaming recurrence. If it writes a line but creates no next due time, compare that occurrence's log with the registry. At the end, first remove this staging event with wp cron event delete atelier_recette_temoin on the same target, check that the filtered list is empty, then deactivate and remove the control plugin. Do not reuse this hook name for real processing.
<?php
/**
* Plugin Name: Atelier — témoin de récurrence
*/
if (!defined('ABSPATH')) {
exit;
}
add_filter('cron_schedules', static function (array $schedules): array {
$schedules['atelier_toutes_les_dix_minutes'] = [
'interval' => 600,
'display' => 'Atelier : toutes les dix minutes',
];
return $schedules;
});
add_action('atelier_recette_temoin', static function (): void {
error_log('ATELIER-CRON : occurrence témoin exécutée');
});Repair frequency loading or remove an old event
For a plugin you maintain, find where its filter is added and action declared. If the filter is attached only in admin_init or while displaying a settings page, move its registration into the plugin's common loading path. Preserve other keys received by the filter. Use a stable name specific to this plugin. If code renamed an old key, decide on event migration: temporarily retaining the old key with the same interval may suit a continuing task, but it does not replace controlled migration when periodicity changes.
When the old occurrence has already disappeared, restoring the filter does not recreate it. Use the plugin's mechanism for initializing or reactivating scheduling after checking that no occurrence already exists for this task and its arguments. In code you own, compare arguments used in lookup and registration: an integer ID and the same ID as a string can represent different WP-Cron entries. Recreating a single row with invented arguments risks triggering another operation or creating a new error.
If the feature was intentionally removed, the expected result changes: the hook should no longer be queued and nothing should produce its old output. Use the plugin's cleanup procedure or ask its maintainer to identify the occurrence to remove. Before deleting a real hook, check whether it carries several tasks and which other components subscribe to it. Do not manually remove a row from the cron array in the database. Emptying the entire queue can remove publications, updates and pending operations unrelated to the fault.
- Record the selected correction: restore the key, migrate a frequency or remove a now-unused task. Back up the code version or setting value enabling targeted rollback.
- Replay the scenario on a copy and compare the queue before and after the first due time. If migrating the event, check that only one occurrence exists for the intended argument combination.
- Also verify the expected processing is present. A properly registered frequency can schedule a hook whose business code is absent; a clean queue does not demonstrate that a report was produced.
Check two due times before closing troubleshooting
Record the UTC time of the first announced event, then the actual first execution time according to the log or business result. Reread the queue immediately afterward: it must contain a later due time with the intended key. Repeat this comparison on the next pass. For an intentionally removed task, instead verify absence of the event and associated trace, with no regression in the control. If the task runs but does not write the expected result, investigate the callback, permissions or data on which it depends.
An old error remains in the log after correction. Filter the period after the change and compare the exact hook. Errors stopping alone is insufficient: if the event disappeared, the log also goes quiet. Useful evidence combines a new due time, a business result and no new error for the retained task. If the control and real hook stop together, check the runner or hosting target. If only the real hook fails, restore the previous code or setting in staging and communicate recurrence and context differences to the maintainer, without a raw log containing arguments.
To reproduce the fault without real data, you can remove the control plugin's filter on a copy while leaving the callback loaded. The already-registered occurrence may still produce its line while the next is not registered. Restore the filter, recreate a control occurrence if it disappeared and repeat both passes. This distinguishes a missing key from a complete scheduler stop. It does not, by itself, prove the forum incident's origin: plugins can also replace scheduling functions or alter their results.
Inspect the task without SSH using WP Crontrol
WP Crontrol lets you read the queue and recurrences in the administration area. On the copy, install the free plugin through Plugins > Add New Plugin, checking its exact name and official listing. Open Cron > Cron Events; Tools > Cron Events also remains documented. Search for the exact hook, then record its recurrence and next due time. Do not click Run now for this diagnosis: that command may actually execute the processing.
Then open Cron > Cron Schedules and look for the key named in the error. A task registered with tenminutes but no such key in this list is a discrepancy to give the code owner. If the key is visible in the administration area, it still does not prove it loads in the HTTP worker: contexts may differ.
Retain only necessary fields, because displayed arguments may contain internal data. Do not manually add a frequency under a third-party plugin's name to conceal the error. After the supplier's fix, reread the next due time after two normal passes. Deactivating the inspection tool must not replace cleanup of a test event you may have created.
Sources and references
Use these references to check the features, requirements and limitations described. Reading documentation is not a practical test.
View 9 references
- WordPress forum — Scheduled events returning errors ↗
- WordPress — wp_reschedule_event() ↗
- WordPress — wp_schedule_event() ↗
- WordPress — cron_schedules filter ↗
- WP-CLI — wp cron schedule list ↗
- WP-CLI — wp cron event list ↗
- WP-CLI — wp cron event schedule ↗
- WP-CLI — wp cron event delete ↗
- Official documentation — Inspect the task without SSH using WP Crontrol ↗


