smarty-php/smarty

Smarty_Internal_Template::render(): Cannot use output buffering in output buffering display handlers

Closed this issue · 7 comments

Not sure if this is a Smarty issue or some bad server configuration or something like that. While running my application with Smarty 4.5.2 on PHP 8.2, no errors or whatsoever appear. Everything renders fine. However, the Apache web server log gets flooded with errors like this:

PHP Fatal error: Smarty_Internal_Template::render(): Cannot use output buffering in output buffering display handlers in vendor/smarty/smarty/libs/sysplugins/smarty_internal_template.php on line 234

Any idea what's going on here?

Without a reproduction scenario it's hard to say. Have you searched for the error online? Maybe this helps: https://stackoverflow.com/questions/33936067/cannot-use-output-buffering-in-output-buffering-display-handlers#34164495

This might suggest that you are calling Smarty from an ob_start callback. But I don't know if that is accurate of course.

I'm not using such a callback. To solve this issue I've had removed my only ob_start('ob_gzhandler'); call and currently using no output buffering at all. The result was the error logged above. Could perhaps a misconfigured php.ini relate to that?

@Chrissyx I've tried to reproduce this, but I can't. Can you show a (preferably minimal) example that triggers this error?

After spending five more hours into researching the issue, I think I finally found it. It happens by displaying a fairly large website with a lot of HTML data. Locally on my machine I got a blank page and this error logged by system:

PHP Fatal error: PHP Request Shutdown: Cannot use output buffering in output buffering display handlers in Unknown on line 0

However by using the debugger on the same view it crashed due to this:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 49690624 bytes) in vendor\smarty\smarty\libs\sysplugins\smarty_internal_template.php on line 234

Note that providing and assigning the data to render is no problem at all. It actually fails by printing out the surrounding tags as stated in the TPL file, e.g. as list entries with images and links. Not sure if Smarty can handle it better, but the initial error was definitely misleading.

That must be a SERIOUSLY complex template if 128MB of RAM isn't enough to render it. Does the problem go away if you bump the PHP limit up to 256MB?

Yes, it solves the problem and the page renders with no errors in the log.
The template is not complex at all, it's just a long list with ~120k entries. I saved the page and it resulted in a 31 MB downloaded HTML file. So yeah, that might explain something.

That sounds about right. At line 234, Smarty retrieves the template output from its internal buffer and writes it to output. If you have your own gzipping output buffer active however, PHP will need to allocate enough space to store the output in memory. From you error message, this is 49690624 bytes or approximately 47 MB which approximately matches your resulting 31 MB downloaded file.

Since the application has already used a bunch of memory for loading the data, the templates and passing the data to the templates, this in turn results in a memory overflow.

One could imagine a more efficient method of rendering the data in smaller batches and eliminating output buffers where possible, but for this use case an increasing the memory limit seems the easiest fix.