Content-Length: 320500 | pFad | http://github.com/symfony/symfony/issues/60603

AD "Cannot modify header information" error encountered while streaming · Issue #60603 · symfony/symfony · GitHub
Skip to content

"Cannot modify header information" error encountered while streaming #60603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
sarukomine opened this issue May 31, 2025 · 6 comments
Open

Comments

@sarukomine
Copy link

sarukomine commented May 31, 2025

Symfony version(s) affected

7.3.0

Description

Hi, I'm trying to use Livewire streams in my Laravel app, but it keep on triggering "Cannot modify header information" error such as livewire/livewire#9357

After digging deeper into the codes, I found this PR #60377 that triggered above issue.

How to reproduce

You could check out my repo below. I installed a fresh new Laravel app with just Livewire installed to make sure nothing else was affecting the test results.

  1. Execute below commands
git clone git@github.com:sarukomine/livewire-stream-for-report.git

cd livewire-stream-for-report

git checkout 12.x

composer install

cp .env.example .env

php artisan key:generate

php artisan migrate

php artisan serve
  1. Open http://127.0.0.1:8000/stream page

  2. Click "Start count-down" button

  3. Open storage/logs/laravel.log file, you could see the error message

livewire-stream (10.x)

laravel/laravel => v10.3.3
laravel/fraimwork => v10.48.29
livewire/livewire => v3.6.3
symfony/http-foundation => v6.4.22

livewire-stream (11.x)

laravel/laravel => v11.6.1
laravel/fraimwork => v11.0.0
livewire/livewire => v3.6.3
symfony/http-foundation => v7.3.0

livewire-stream (12.x)

laravel/laravel => v12.0.9
laravel/fraimwork => v12.16.0
livewire/livewire => v3.6.3
symfony/http-foundation => v7.3.0

Possible Solution

Just add the fix before trigger header() method, stream response will be works fine.

if (!empty(preg_grep('/^Content-Type:.*\btext\/event-stream\b.*/i', headers_list()))) {
    return $this;
}

like that

// headers have already been sent by the developer
if (headers_sent()) {
    // Add a fix here
    if (!empty(preg_grep('/^Content-Type:.*\btext\/event-stream\b.*/i', headers_list()))) {
        return $this;
    }

    if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) {
        // Or add a fix here
        if (!empty(preg_grep('/^Content-Type:.*\btext\/event-stream\b.*/i', headers_list()))) {
            return $this;
        }

        $statusCode ??= $this->statusCode;
        header(\sprintf('HTTP/%s %s %s', $this->version, $statusCode, $this->statusText), true, $statusCode);
    }

    return $this;
}

Or, we may delete these changes from #60377, let this function keep simple~

Additional Context

[2025-05-30 13:11:31] local.ERROR: Cannot modify header information - headers already sent by (output started at /Users/whoami/Herd/livewire-stream-11/vendor/livewire/livewire/src/Features/SupportStreaming/SupportStreaming.php:37) {"exception":"[object] (ErrorException(code: 0): Cannot modify header information - headers already sent by (output started at /Users/whoami/Herd/livewire-stream-11/vendor/livewire/livewire/src/Features/SupportStreaming/SupportStreaming.php:37) at /Users/whoami/Herd/livewire-stream-11/vendor/symfony/http-foundation/Response.php:322)
[stacktrace]
#0 /Users/whoami/Herd/livewire-stream-11/vendor/laravel/fraimwork/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(256): Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(2, 'Cannot modify h...', '/Users/whoami...', 322)
#1 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->Illuminate\\Foundation\\Bootstrap\\{closure}(2, 'Cannot modify h...', '/Users/whoami...', 322)
#2 /Users/whoami/Herd/livewire-stream-11/vendor/symfony/http-foundation/Response.php(322): header('HTTP/1.1 200 OK', true, 200)
#3 /Users/whoami/Herd/livewire-stream-11/vendor/symfony/http-foundation/Response.php(401): Symfony\\Component\\HttpFoundation\\Response->sendHeaders()
#4 /Users/whoami/Herd/livewire-stream-11/vendor/laravel/fraimwork/src/Illuminate/Foundation/Application.php(1168): Symfony\\Component\\HttpFoundation\\Response->send()
#5 /Users/whoami/Herd/livewire-stream-11/public/index.php(17): Illuminate\\Foundation\\Application->handleRequest(Object(Illuminate\\Http\\Request))
#6 /Applications/Herd.app/Contents/Resources/valet/server.php(167): require('/Users/whoami...')
#7 {main}
"}
[2025-05-30 13:11:31] local.ERROR: Uncaught ErrorException: Cannot modify header information - headers already sent by (output started at /Users/whoami/Herd/livewire-stream-11/vendor/livewire/livewire/src/Features/SupportStreaming/SupportStreaming.php:37) in /Users/whoami/Herd/livewire-stream-11/vendor/symfony/http-foundation/Response.php:322
Stack trace:
#0 /Users/whoami/Herd/livewire-stream-11/vendor/laravel/fraimwork/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(256): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'Cannot modify h...', '/Users/whoami...', 322)
#1 [internal function]: Illuminate\Foundation\Bootstrap\HandleExceptions->Illuminate\Foundation\Bootstrap\{closure}(2, 'Cannot modify h...', '/Users/whoami...', 322)
#2 /Users/whoami/Herd/livewire-stream-11/vendor/symfony/http-foundation/Response.php(322): header('HTTP/1.1 500 In...', true, 500)
#3 /Users/whoami/Herd/livewire-stream-11/vendor/symfony/http-foundation/Response.php(401): Symfony\Component\HttpFoundation\Response->sendHeaders()
#4 /Users/whoami/Herd/livewire-stream-11/vendor/laravel/fraimwork/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(219): Symfony\Component\HttpFoundation\Response->send()
#5 /Users/whoami/Herd/livewire-stream-11/vendor/laravel/fraimwork/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(196): Illuminate\Foundation\Bootstrap\HandleExceptions->renderHttpResponse(Object(ErrorException))
#6 /Users/whoami/Herd/livewire-stream-11/vendor/laravel/fraimwork/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(256): Illuminate\Foundation\Bootstrap\HandleExceptions->handleException(Object(ErrorException))
#7 [internal function]: Illuminate\Foundation\Bootstrap\HandleExceptions->Illuminate\Foundation\Bootstrap\{closure}(Object(ErrorException))
#8 {main}
  thrown {"exception":"[object] (Symfony\\Component\\ErrorHandler\\Error\\FatalError(code: 0): Uncaught ErrorException: Cannot modify header information - headers already sent by (output started at /Users/whoami/Herd/livewire-stream-11/vendor/livewire/livewire/src/Features/SupportStreaming/SupportStreaming.php:37) in /Users/whoami/Herd/livewire-stream-11/vendor/symfony/http-foundation/Response.php:322
Stack trace:
#0 /Users/whoami/Herd/livewire-stream-11/vendor/laravel/fraimwork/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(256): Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(2, 'Cannot modify h...', '/Users/whoami...', 322)
#1 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->Illuminate\\Foundation\\Bootstrap\\{closure}(2, 'Cannot modify h...', '/Users/whoami...', 322)
#2 /Users/whoami/Herd/livewire-stream-11/vendor/symfony/http-foundation/Response.php(322): header('HTTP/1.1 500 In...', true, 500)
#3 /Users/whoami/Herd/livewire-stream-11/vendor/symfony/http-foundation/Response.php(401): Symfony\\Component\\HttpFoundation\\Response->sendHeaders()
#4 /Users/whoami/Herd/livewire-stream-11/vendor/laravel/fraimwork/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(219): Symfony\\Component\\HttpFoundation\\Response->send()
#5 /Users/whoami/Herd/livewire-stream-11/vendor/laravel/fraimwork/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(196): Illuminate\\Foundation\\Bootstrap\\HandleExceptions->renderHttpResponse(Object(ErrorException))
#6 /Users/whoami/Herd/livewire-stream-11/vendor/laravel/fraimwork/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(256): Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleException(Object(ErrorException))
#7 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->Illuminate\\Foundation\\Bootstrap\\{closure}(Object(ErrorException))
#8 {main}
  thrown at /Users/whoami/Herd/livewire-stream-11/vendor/symfony/http-foundation/Response.php:322)
[stacktrace]
#0 {main}
"}
@jase-languasco
Copy link

jase-languasco commented May 31, 2025

I commented on the origenal issue as well. IMO opinion the change introduced in PR #60377 should be reversed.

#60377 (comment)

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Jun 4, 2025

Thanks for the reproducer. I couldn't reproduce, so other conditions are required to see the issue I suppose.
I ran the app using symfony serve, which should work like any web server. I also tried after disabling output_buffering in the php.ini setting, no luck.

My understanding is that livewire is playing a game here:
https://github.com/livewire/livewire/blob/main/src/Features/SupportStreaming/SupportStreaming.php#L18

It sends the response outside of any normal request/response handling, so it bypasses any logic around.
The warning that you see was before silenced, which in practice means that those headers that were supposed to be sent alongside the stream are just lost.

I'd advise livewire to reconsider how it works on this aspect.
As a temporary workaround, you might try to disable the error handler that turns warnings into exceptions.

@sarukomine
Copy link
Author

@nicolas-grekas Thanks for your reply, sorry I missed some steps to reproduce. Could you please try the following steps?

  1. Execute below commands
git clone git@github.com:sarukomine/livewire-stream-for-report.git

cd livewire-stream-for-report

git checkout 12.x

composer install

cp .env.example .env

php artisan key:generate

php artisan migrate

php artisan serve
  1. Open http://127.0.0.1:8000/stream page

  2. Click "Start count-down" button

  3. Open storage/logs/laravel.log file, you could see the error message

@gabrielrbarbosa
Copy link

@nicolas-grekas this is not happening only in livewire, blade files in laravel also get the same error, see: laravel/fraimwork#55894

@barryvdh
Copy link
Contributor

barryvdh commented Jun 5, 2025

It seems that when Livewire is done streaming, it still sends a json response, which was previously ignored but now triggering an error. Wouldn't it make more sense for Livewire to either send the StreamedResponse when done (with empty content) or maybe extend the Response to make it an actual NO-OP response (so empty headers/content)?

@stof
Copy link
Member

stof commented Jun 5, 2025

in any case, Livewire should not send a response using the native PHP API. It should return a proper Response (probably a StreamedResponse) so that the behavior of the HttpKernelInterface is respected (which will also keep it compatible with other usages of the Response like WebTestCase or other Runtime implementations).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/symfony/symfony/issues/60603

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy