Opened 8 weeks ago
Last modified 4 days ago
#63987 new defect (bug)
wp_get_scheduled_event() incorrectly returns false for cron events scheduled with a timestamp of 0.
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | 7.0 | Priority: | normal |
| Severity: | normal | Version: | |
| Component: | Cron API | Keywords: | has-patch has-unit-tests has-test-info needs-testing 2nd-opinion |
| Focuses: | Cc: |
Description
When using the wp_get_scheduled_event() function to retrieve a scheduled cron event, it incorrectly returns false if the event's timestamp is exactly 0 (the Unix epoch).
wp_get_scheduled_event can be found in wp-includes/cron.php:787
The issue
The issue lies in this line:
<?php if ( ! $timestamp ) {
In PHP, the integer 0 is evaluated as false in a boolean context. This causes the function to enter the "get next event" block, which then fails to find the event at timestamp 0 and ultimately returns false, despite the event existing in the cron array.
How to Reproduce
Schedule a cron event with a timestamp of 0. You can do this by manually adding it to the cron array or by using a function like this:
<?php // Add an event with a timestamp of 0. // This is for demonstration purposes. In a real scenario, this might happen due to a bug in a plugin. $crons = _get_cron_array(); $crons[0]['my_test_hook']['unique_key'] = array( 'schedule' => false, 'args' => array(), ); _set_cron_array($crons);
Attempt to retrieve this specific event using wp_get_scheduled_event() with the timestamp 0:
<?php $event = wp_get_scheduled_event( 'my_test_hook', array(), 0 );
Check the result.
<?php if ( false === $event ) { echo "The function returned false. This is the bug."; } else { echo "The function correctly found the event."; }
Expected behavior: The function should return the event object, as the event with a timestamp of 0 exists.
Current behavior: The function returns false, indicating the event does not exist. So i cannot remove that event from the cron array using wp_unschedule_event
Suggested Fix
A possible fix is to change the if condition to be more explicit, for example:
<?php if ( null === $timestamp ) {
This would only trigger the "get next event" logic when no timestamp is provided, correctly handling a timestamp of 0 as a valid value.
Change History (12)
This ticket was mentioned in PR #9914 on WordPress/wordpress-develop by @rishabhwp.
8 weeks ago
#2
- Keywords has-patch has-unit-tests added; needs-patch needs-unit-tests removed
#4
@
7 weeks ago
- Keywords dev-feedback changes-requested added
Hey @rishabhwp,
I see that you have this code in wp_unschedule_event but not in wp_schedule_single_event?:
if ( ! is_numeric( $timestamp ) || $timestamp < 0 ) {
When in fact both function shares same validation?
#5
@
7 weeks ago
- Keywords has-test-info added
Reproduction Report
Description
This report validates whether the issue can be reproduced.
The attached test plugin (Ticket 63987) injects two cron events for the same hook my_test_hook:
- One at timestamp
0(bug case). - One at a non-zero future timestamp (control case).
When calling wp_get_scheduled_event() with timestamp 0, the function incorrectly returns false.
Environment
- WordPress: 6.9-alpha-60093-src
- PHP: 8.2.29
- Server: nginx/1.29.1
- Database: mysqli (Server: 8.4.6 / Client: mysqlnd 8.2.29)
- Browser: Chrome 139.0.0.0
- OS: Linux
- Theme: Twenty Twenty-Five 1.3
- MU Plugins: None activated
- Plugins:
- Test Reports 1.2.0
- Ticket 63987 1.0
Steps to Reproduce
- Activate the
Ticket 63987plugin. - Visit any front-end page with
?test-cron=1appended to the URL. - The plugin injects two events and dumps the results of
wp_get_scheduled_event().
Actual Results
- For timestamp
0:
bool(false)
- For the future timestamp:
object(stdClass)#311 (4) {
["hook"]=>
string(12) "my_test_hook"
["timestamp"]=>
int(1758456619)
["schedule"]=>
bool(false)
["args"]=>
array(0) {
}
}
✅ Error condition occurs (reproduced).
Expected Results
- For timestamp
0, the event should be returned in the same format as the non-zero timestamp event. It should be:
object(stdClass)[312]
public 'hook' => string 'my_test_hook' (length=12)
public 'timestamp' => int 0
public 'schedule' => boolean false
public 'args' =>
array (size=0)
- Returning
falseis incorrect since the event exists in the cron array.
Additional Notes
- This confirms that the falsy check for
$timestampinwp_get_scheduled_event()causes timestamp0to be treated as "no timestamp." - Non-zero timestamps behave as expected.
Supplemental Artifacts
Inline test plugin code for reproduction:
<?php
/**
* Plugin Name: Ticket 63987
* Description: Demonstrates the bug in wp_get_scheduled_event() when timestamp is 0.
* Version: 1.0
* Author: Rolly Bueno
*/
add_action( 'init', 'test_cron_zero_timestamp' );
function test_cron_zero_timestamp() {
if ( ! isset( $_GET['test-cron'] ) ) {
return;
}
// 1. Inject a cron event at timestamp 0 (bug case).
$crons = _get_cron_array();
$args = array();
$key = md5( serialize( $args ) );
$crons[0]['my_test_hook'][ $key ] = array(
'schedule' => false,
'args' => $args,
);
// 2. Inject a cron event at a non-zero timestamp (valid case).
$future = time() + 3600; // 1 hour from now
$crons[ $future ]['my_test_hook'][ $key ] = array(
'schedule' => false,
'args' => $args,
);
// Save back into cron array.
_set_cron_array( $crons );
// 3. Try fetching both.
$event_zero = wp_get_scheduled_event( 'my_test_hook', array(), 0 );
$event_future = wp_get_scheduled_event( 'my_test_hook', array(), $future );
// 4. Output results.
echo '<pre>';
echo "Testing wp_get_scheduled_event()\n\n";
echo "At timestamp 0:\n";
var_dump( $event_zero );
echo "\nAt timestamp {$future}:\n";
var_dump( $event_future );
echo '</pre>';
exit;
}
(Correct result) If https://github.com/WordPress/WordPress/blob/master/wp-includes/cron.php#L787 updated into if ( null === $timestamp ) {:

#6
@
7 weeks ago
I left a review feedback on https://github.com/WordPress/wordpress-develop/pull/9914, which needs an update before putting this to needs-testing
#7
@
7 weeks ago
- Keywords needs-testing added; dev-feedback changes-requested removed
Changes set - adding needs-testing
#8
@
5 weeks ago
- Keywords 2nd-opinion added
It appears this behavior is intentional, since the helper functions for scheduling events return false and/or a WP_Error object when a timestamp of 0 is provided. (wp_schedule_event, wp_schedule_single_event, wp_reschedule_event, wp_unschedule_event). / Example
If using wp_schedule_event() or related, this bug doesn't really exist because the 0 timestamp is considered invalid and it won't be added to the cron array.
0 is a valid timestamp, but is there a use case for scheduling events at 0? What would be the purpose of scheduling at 0, instead of say now() or even 1?
In the original ticket, the example uses _set_cron_array(), which is marked as private in the phpdocs, like many/most functions in WP that begin with the _ character.

Thanks for the report @codekraft !