frankenphp icon indicating copy to clipboard operation
frankenphp copied to clipboard

"Session cannot be started after headers have already been sent" with `flush()` placed before `session_start()`

Open Gautrot opened this issue 6 months ago • 0 comments

What happened?

This issue happens with FrankenPHP 1.7.0 only.

An issue has been happening with flush() when it is used before session_start().

This leads to an error with PHP sessions and cannot create a session with session_start(), as headers were already sent by then. This issue was introduced by 1.7.0 (#1622).

It is replicable in index.php with this example:

<?php

ignore_user_abort(true);

$handler = static function () {
    // Test case: logging a content with stdout
    $fp = fopen('php://stdout', 'w');
    fwrite($fp, 'test');
    flush(); // The root cause (Warning: session_start(): Session cannot be started after headers have already been sent in /app/public/index.php)
    fclose($fp);
    session_start();
};

$maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0);
for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests) {
    $keepRunning = frankenphp_handle_request($handler);

    gc_collect_cycles();

    if (!$keepRunning) break;
}

Build Type

Docker (Debian Bookworm)

Worker Mode

Yes

Operating System

GNU/Linux

CPU Architecture

x86_64

PHP configuration

System 	Linux d2d83dbf955b 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025 x86_64
Build Date 	Jun 6 2025 17:37:09
Build System 	Linux - Docker
Build Provider 	https://github.com/docker-library/php
Configure Command 	'./configure' '--build=x86_64-linux-gnu' '--with-config-file-path=/usr/local/etc/php' '--with-config-file-scan-dir=/usr/local/etc/php/conf.d' '--enable-option-checking=fatal' '--with-mhash' '--with-pic' '--enable-mbstring' '--enable-mysqlnd' '--with-password-argon2' '--with-sodium=shared' '--with-pdo-sqlite=/usr' '--with-sqlite3=/usr' '--with-curl' '--with-iconv' '--with-openssl' '--with-readline' '--with-zlib' '--enable-phpdbg' '--enable-phpdbg-readline' '--with-pear' '--with-libdir=lib/x86_64-linux-gnu' '--enable-embed' '--enable-zts' '--disable-zend-signals' 'build_alias=x86_64-linux-gnu' 'PHP_UNAME=Linux - Docker' 'PHP_BUILD_PROVIDER=https://github.com/docker-library/php'
Server API 	FrankenPHP
Virtual Directory Support 	enabled
Configuration File (php.ini) Path 	/usr/local/etc/php
Loaded Configuration File 	(none)
Scan this dir for additional .ini files 	/usr/local/etc/php/conf.d
Additional .ini files parsed 	/usr/local/etc/php/conf.d/docker-php-ext-sodium.ini
PHP API 	20240924
PHP Extension 	20240924
Zend Extension 	420240924
Zend Extension Build 	API420240924,TS
PHP Extension Build 	API20240924,TS
PHP Integer Size 	64 bits
Debug Build 	no
Thread Safety 	enabled
Thread API 	POSIX Threads
Zend Signal Handling 	disabled
Zend Memory Manager 	enabled
Zend Multibyte Support 	provided by mbstring
Zend Max Execution Timers 	enabled
IPv6 Support 	enabled
DTrace Support 	disabled
Registered PHP Streams	https, ftps, compress.zlib, php, file, glob, data, http, ftp, phar
Registered Stream Socket Transports	tcp, udp, unix, udg, ssl, tls, tlsv1.0, tlsv1.1, tlsv1.2, tlsv1.3
Registered Stream Filters	zlib.*, convert.iconv.*, string.rot13, string.toupper, string.tolower, convert.*, consumed, dechunk

Relevant log output

Warning: session_start(): Session cannot be started after headers have already been sent in /app/public/index.php on line 11

Gautrot avatar Jun 20 '25 09:06 Gautrot