#57475 closed defect (bug) (worksforme)
wp_schedule_event function causes "Headers already sent" error
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Priority: | normal | |
| Severity: | normal | Version: | 6.1.1 |
| Component: | Cron API | Keywords: | has-test-info |
| Focuses: | Cc: |
Description
I need to start the PHP session for my plugin. On plugin activation, I am getting PHP Warning.
PHP Warning: session_start(): Cannot start session when headers already sent in..
On register_activation_hook I am using wp_schedule_event() to register my custom event hook. If I remove wp_schedule_event() I don't see the PHP Warning. So we can say that the wp_schedule_event function prints something that causes the Warning.
To test this issue use my simple plugin code below.
<?php /** * Plugin Name: Test plugin * Description: Just a Test plugin * Plugin URI: http://onetarek.com * Author: oneTarek * Author URI: http://onetarek.com * Version: 1.0.0 */ function test_activation() { wp_schedule_event( time(), 'daily', 'test_daily_event_hook' ); } function test_deactivation() { wp_clear_scheduled_hook( 'test_daily_event_hook' ); } register_activation_hook( __FILE__, 'test_activation' ); register_deactivation_hook( __FILE__, 'test_deactivation' ); if( session_id() == "" ){ session_start(); }
Install this plugin code. Activate and check debug log. Try activating and deactivating this plugin multiple times if you don't see any Warning.
Attachments (1)
Change History (6)
#1
@
3 years ago
My site info
WP Version: 6.1.1
PHP version: 7.3.5 (Supports 64bit values)
Web server: Apache/2.4.43 (Unix)
Server architecture: Darwin 17.7.0 x86_64
#2
follow-up:
↓ 3
@
3 years ago
The warnings in your logs are occurring when the cron job test_daily_event_hook runs, they're not running due to the call to wp_schedule_event().
Calls to wp-cron.php send the headers early in the request. The unconditional call to start the session in your plugin will then attempt to start a session on the wp-cron.php request.
[16-Jan-2023 21:36:55 UTC] PHP Stack trace:
[16-Jan-2023 21:36:55 UTC] PHP 1. {main}() /vagrant/wordpress-develop/src/wp-cron.php:0
[16-Jan-2023 21:36:55 UTC] PHP 2. require_once() /vagrant/wordpress-develop/src/wp-cron.php:46
[16-Jan-2023 21:36:55 UTC] PHP 3. require_once() /vagrant/wordpress-develop/src/wp-load.php:50
[16-Jan-2023 21:36:55 UTC] PHP 4. include() /vagrant/wordpress-develop/src/wp-config.php:9
[16-Jan-2023 21:36:55 UTC] PHP 5. require_once() /vagrant/wp-config.php:147
[16-Jan-2023 21:36:55 UTC] PHP 6. include_once() /vagrant/wordpress-develop/src/wp-settings.php:447
[16-Jan-2023 21:36:55 UTC] PHP 7. session_start() /vagrant/content/plugins/cron-test-plugin/plugin.php:24
WP-cron doesn't support headers or sessions as it can be run either within the browser or via the CLI. I suggest you wrap the call to session_start() in a conditional to ensure it only runs in browser requests.
#3
in reply to:
↑ 2
@
3 years ago
- Resolution set to invalid
- Status changed from new to closed
Replying to peterwilsoncc:
The warnings in your logs are occurring when the cron job
test_daily_event_hookruns, they're not running due to the call towp_schedule_event().
Calls to wp-cron.php send the headers early in the request. The unconditional call to start the session in your plugin will then attempt to start a session on the wp-cron.php request.
[16-Jan-2023 21:36:55 UTC] PHP Stack trace: [16-Jan-2023 21:36:55 UTC] PHP 1. {main}() /vagrant/wordpress-develop/src/wp-cron.php:0 [16-Jan-2023 21:36:55 UTC] PHP 2. require_once() /vagrant/wordpress-develop/src/wp-cron.php:46 [16-Jan-2023 21:36:55 UTC] PHP 3. require_once() /vagrant/wordpress-develop/src/wp-load.php:50 [16-Jan-2023 21:36:55 UTC] PHP 4. include() /vagrant/wordpress-develop/src/wp-config.php:9 [16-Jan-2023 21:36:55 UTC] PHP 5. require_once() /vagrant/wp-config.php:147 [16-Jan-2023 21:36:55 UTC] PHP 6. include_once() /vagrant/wordpress-develop/src/wp-settings.php:447 [16-Jan-2023 21:36:55 UTC] PHP 7. session_start() /vagrant/content/plugins/cron-test-plugin/plugin.php:24WP-cron doesn't support headers or sessions as it can be run either within the browser or via the CLI. I suggest you wrap the call to
session_start()in a conditional to ensure it only runs in browser requests.
@peterwilsoncc You are right. The header is being sent from wp-cron.php. I put my code in a condition.
<?php if( "" == session_id() && !defined( 'DOING_CRON' ) && !isset( $_GET['doing_wp_cron'] ) ){ session_start(); }
Now there is no warning.
#4
@
3 years ago
- Milestone Awaiting Review deleted
- Resolution changed from invalid to worksforme
Thanks for following up, I appreciate the confirmation I wasn't missing an edge case.
I'll close this issue off as worksforme as it's expected behavior for wp-cron to send headers early.
You might need to change a few other things to do with sessions in your plugin but the best place to get assistance for such things is in the Developing with WordPress forum, the folks who hang around there are much better placed to assist.
A very simple plugin to test the issue