Attachments are not available anymore for download via browser from page "ERR_INVALID_RESPONSE" #2778

Closed
opened 2026-02-05 05:09:49 +03:00 by OVERLORD · 13 comments
Owner

Originally created by @whentotrade on GitHub (May 4, 2022).

Describe the Bug

I had a bookstack running site with pages and attachments. After latest upgrade to v22.04, now all attachments are still shown but if you click an attachment no attachment can be downloaded and the browser just shows "ERR_INVALID_RESPONSE".

For all attachments on the site https://docs.cycle.tools/attachments/[NUMBER]

Attchment downloading has been working before - so no change in content on my pages.

Even if I start to upload a new attachment (which works) - if I try to read the page and try to download it from the page, I get the "ERR INVALID RESPONSE" in the browser window.

What has happened that now all browser URLS like https://docs.cycle.tools/attachments/[NUMBER] result in an "ERR INVALID RESPONSE"?

Steps to Reproduce

  1. Go to: https://docs.cycle.tools/books/cycle-tools-app-manual/page/upload-your-own-data
  2. Try to click one of the two attachment links in the upper left corner
  3. Error message appears

Expected Behaviour

Download should start after click on attachment - as it did before upgrade.

Screenshots or Additional Context

image

Browser Details

Chrome

Exact BookStack Version

v 22.04

PHP Version

7.4

Hosting Environment

Linux

Originally created by @whentotrade on GitHub (May 4, 2022). ### Describe the Bug I had a bookstack running site with pages and attachments. After latest upgrade to v22.04, now all attachments are still shown but if you click an attachment no attachment can be downloaded and the browser just shows "ERR_INVALID_RESPONSE". For all attachments on the site https://docs.cycle.tools/attachments/[NUMBER] Attchment downloading has been working before - so no change in content on my pages. Even if I start to upload a new attachment (which works) - if I try to read the page and try to download it from the page, I get the "ERR INVALID RESPONSE" in the browser window. What has happened that now all browser URLS like https://docs.cycle.tools/attachments/[NUMBER] result in an "ERR INVALID RESPONSE"? ### Steps to Reproduce 1. Go to: https://docs.cycle.tools/books/cycle-tools-app-manual/page/upload-your-own-data 2. Try to click one of the two attachment links in the upper left corner 3. Error message appears ### Expected Behaviour Download should start after click on attachment - as it did before upgrade. ### Screenshots or Additional Context ![image](https://user-images.githubusercontent.com/30272473/166750697-9bb28087-fffc-4791-acd3-1ae04d47d9be.png) ### Browser Details Chrome ### Exact BookStack Version v 22.04 ### PHP Version 7.4 ### Hosting Environment Linux
OVERLORD added the 🐛 Bug label 2026-02-05 05:09:49 +03:00
Author
Owner

@ssddanbrown commented on GitHub (May 4, 2022):

Hi @whentotrade,
Thanks for reporting.

In v22.04 I did indeed change how attachments are served, for better efficiency to help the handling of large files.
Unfortunately I am not able to re-produce on my own BookStack environment, even using the exact same attachment file as you have on yours.
Interestingly your attachments serve without error via the "open" url variation, often accessed by Ctrl+Clicking the attachment, as per this URL an an example:
https://docs.cycle.tools/attachments/7?open=true

There's not a massive amount of difference between the two attachment download types. In fact, the working "open" variation is a little more technically complex.
Could you check your error logs for any error output upon seeing this error? My guess would be the error would be in the Apache logs, since it does not appear that BookStack is handling this error, but I might be wrong.

@ssddanbrown commented on GitHub (May 4, 2022): Hi @whentotrade, Thanks for reporting. In v22.04 I did indeed change how attachments are served, for better efficiency to help the handling of large files. Unfortunately I am not able to re-produce on my own BookStack environment, even using the exact same attachment file as you have on yours. Interestingly your attachments serve without error via the "open" url variation, often accessed by Ctrl+Clicking the attachment, as per this URL an an example: https://docs.cycle.tools/attachments/7?open=true There's not a massive amount of difference between the two attachment download types. In fact, the working "open" variation is a little more technically complex. Could you check your [error logs](https://www.bookstackapp.com/docs/admin/debugging/) for any error output upon seeing this error? My guess would be the error would be in the Apache logs, since it does not appear that BookStack is handling this error, but I might be wrong.
Author
Owner

@anonymous-gituser commented on GitHub (May 5, 2022):

Browser Details
Brave

Exact BookStack Version
v 22.04

PHP Version
7.4

Hosting Environment
Linux

I just installed BookStack yesterday, and was having trouble with a very similar if not the same issue as listed above.

My log files stated that it couldn't delete a buffer using ob_end_clean().

Capture

I commented out the lines
if (!app()->runningUnitTests()) {
ob_end_clean();
}
and it works to download files now.

Thought I'd mention it, but additionally wanted to see if you thought this would cause an issue down the road?

@anonymous-gituser commented on GitHub (May 5, 2022): Browser Details Brave Exact BookStack Version v 22.04 PHP Version 7.4 Hosting Environment Linux I just installed BookStack yesterday, and was having trouble with a very similar if not the same issue as listed above. My log files stated that it couldn't delete a buffer using ob_end_clean(). ![Capture](https://user-images.githubusercontent.com/105015479/167011111-2ac56396-8056-4eaf-95bb-66d86c4273a8.PNG) I commented out the lines if (!app()->runningUnitTests()) { ob_end_clean(); } and it works to download files now. Thought I'd mention it, but additionally wanted to see if you thought this would cause an issue down the road?
Author
Owner

@whentotrade commented on GitHub (May 5, 2022):

Thanks @ssddanbrown , the only error I can spot is in the laravel bookstack logs when trying to open the "attachments" URL:

[2022-05-05 19:25:31] production.ERROR: ob_end_clean(): failed to delete buffer. No buffer to delete {"exception":"[object] (ErrorException(code: 0): ob_end_clean(): failed to delete buffer. No buffer to delete at .../htdocs/bookstack/BookStack/app/Http/Controllers/Controller.php:133)

[stacktrace]
#0 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(8, 'ob_end_clean():...', '/homepages/32/d...', 133, Array)
#1 ../htdocs/bookstack/BookStack/app/Http/Controllers/Controller.php(133): ob_end_clean()
#2 ../htdocs/bookstack/BookStack/vendor/symfony/http-foundation/StreamedResponse.php(109): BookStack\\Http\\Controllers\\Controller->BookStack\\Http\\Controllers\\{closure}()
#3 .../htdocs/bookstack/BookStack/vendor/symfony/http-foundation/Response.php(394): Symfony\\Component\\HttpFoundation\\StreamedResponse->sendContent()
#4 .../htdocs/bookstack/BookStack/vendor/laravel/framework/src/Illuminate/Support/HigherOrderTapProxy.php(34): Symfony\\Component\\HttpFoundation\\Response->send()
#5 .../htdocs/bookstack/BookStack/public/index.php(54): Illuminate\\Support\\HigherOrderTapProxy->__call('send', Array)
#6 {main}
"} 

maybe this is related to the download call? As I see the following code around line 133:


    /**
     * Create a response that forces a download, from a given stream of content.
     */
    protected function streamedDownloadResponse($stream, string $fileName): StreamedResponse
    {
        return response()->stream(function () use ($stream) {
            // End & flush the output buffer otherwise we still seem to use memory.
            // Ignore in testing since output buffers are used to gather a response.
            if (!app()->runningUnitTests()) {
                ob_end_clean();     // <------------------------ LINE CAUSING ERROR ???????????
            }

            fpassthru($stream);
            fclose($stream);
        }, 200, [
            'Content-Type'           => 'application/octet-stream',
            'Content-Disposition'    => 'attachment; filename="' . str_replace('"', '', $fileName) . '"',
            'X-Content-Type-Options' => 'nosniff',
        ]);
    }


I am not able to find other errors in the log?

Does this help?

It is really a problem for me as usage depends on being able to download attachments. Which is not possible for all attachments now. It is not related to specific file types - all attachment downloads result now in that error.

Any hint to solve would help. If you need additional information, please let me know.

@whentotrade commented on GitHub (May 5, 2022): Thanks @ssddanbrown , the only error I can spot is in the laravel bookstack logs when trying to open the "attachments" URL: ``` [2022-05-05 19:25:31] production.ERROR: ob_end_clean(): failed to delete buffer. No buffer to delete {"exception":"[object] (ErrorException(code: 0): ob_end_clean(): failed to delete buffer. No buffer to delete at .../htdocs/bookstack/BookStack/app/Http/Controllers/Controller.php:133) [stacktrace] #0 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(8, 'ob_end_clean():...', '/homepages/32/d...', 133, Array) #1 ../htdocs/bookstack/BookStack/app/Http/Controllers/Controller.php(133): ob_end_clean() #2 ../htdocs/bookstack/BookStack/vendor/symfony/http-foundation/StreamedResponse.php(109): BookStack\\Http\\Controllers\\Controller->BookStack\\Http\\Controllers\\{closure}() #3 .../htdocs/bookstack/BookStack/vendor/symfony/http-foundation/Response.php(394): Symfony\\Component\\HttpFoundation\\StreamedResponse->sendContent() #4 .../htdocs/bookstack/BookStack/vendor/laravel/framework/src/Illuminate/Support/HigherOrderTapProxy.php(34): Symfony\\Component\\HttpFoundation\\Response->send() #5 .../htdocs/bookstack/BookStack/public/index.php(54): Illuminate\\Support\\HigherOrderTapProxy->__call('send', Array) #6 {main} "} ``` maybe this is related to the download call? As I see the following code around line 133: ``` /** * Create a response that forces a download, from a given stream of content. */ protected function streamedDownloadResponse($stream, string $fileName): StreamedResponse { return response()->stream(function () use ($stream) { // End & flush the output buffer otherwise we still seem to use memory. // Ignore in testing since output buffers are used to gather a response. if (!app()->runningUnitTests()) { ob_end_clean(); // <------------------------ LINE CAUSING ERROR ??????????? } fpassthru($stream); fclose($stream); }, 200, [ 'Content-Type' => 'application/octet-stream', 'Content-Disposition' => 'attachment; filename="' . str_replace('"', '', $fileName) . '"', 'X-Content-Type-Options' => 'nosniff', ]); } ``` I am not able to find other errors in the log? Does this help? It is really a problem for me as usage depends on being able to download attachments. Which is not possible for all attachments now. It is not related to specific file types - all attachment downloads result now in that error. Any hint to solve would help. If you need additional information, please let me know.
Author
Owner

@whentotrade commented on GitHub (May 5, 2022):

Just a hint, I have spotted the error:

If I disable this line in the function "Create a response that forces a download, from a given stream of content.":

ob_end_clean();

The download function works as normal again. But this seems to be a bad workaround for me know manually changing the code to get it working. I just dont know why this line is the root cause of this problem on my server?

Changing the code worked:

/**
 * Create a response that forces a download, from a given stream of content.
 */
protected function streamedDownloadResponse($stream, string $fileName): StreamedResponse
{
    return response()->stream(function () use ($stream) {
        // End & flush the output buffer otherwise we still seem to use memory.
        // Ignore in testing since output buffers are used to gather a response.
        if (!app()->runningUnitTests()) {
            //ob_end_clean();   <----------------------------- CHANGE DONE HERE ----------------------------
        }

        fpassthru($stream);
        fclose($stream);
    }, 200, [
        'Content-Type'           => 'application/octet-stream',
        'Content-Disposition'    => 'attachment; filename="' . str_replace('"', '', $fileName) . '"',
        'X-Content-Type-Options' => 'nosniff',
    ]);
}
@whentotrade commented on GitHub (May 5, 2022): Just a hint, I have spotted the error: If I disable this line in the function "Create a response that forces a download, from a given stream of content.": `ob_end_clean();` The download function works as normal again. But this seems to be a bad workaround for me know manually changing the code to get it working. I just dont know why this line is the root cause of this problem on my server? Changing the code worked: /** * Create a response that forces a download, from a given stream of content. */ protected function streamedDownloadResponse($stream, string $fileName): StreamedResponse { return response()->stream(function () use ($stream) { // End & flush the output buffer otherwise we still seem to use memory. // Ignore in testing since output buffers are used to gather a response. if (!app()->runningUnitTests()) { //ob_end_clean(); <----------------------------- CHANGE DONE HERE ---------------------------- } fpassthru($stream); fclose($stream); }, 200, [ 'Content-Type' => 'application/octet-stream', 'Content-Disposition' => 'attachment; filename="' . str_replace('"', '', $fileName) . '"', 'X-Content-Type-Options' => 'nosniff', ]); }
Author
Owner

@whentotrade commented on GitHub (May 5, 2022):

Any idea how to finally solve it without the need to manualy alter the code?

@whentotrade commented on GitHub (May 5, 2022): Any idea how to finally solve it without the need to manualy alter the code?
Author
Owner

@whentotrade commented on GitHub (May 5, 2022):

@anonymous-gituser Thanks for posting - I think we responded at the same time;-)

@whentotrade commented on GitHub (May 5, 2022): @anonymous-gituser Thanks for posting - I think we responded at the same time;-)
Author
Owner

@ssddanbrown commented on GitHub (May 5, 2022):

Thanks for the information @whentotrade and @anonymous-gituser, Looks like the same line is tripping up both instances. This line, during my testing, does serve a purpose primarily for large attachment downloads to ensure that less memory is used. Most existing smaller attachments downloads should work without this line, but I'd rather find out why this is a problem in some environments.

Could you both share further insight regarding your hosting environment?
What linux distro and what exact version is it?
What version of PHP are you using?
What webserver are you using?
Are you using some kind of hosting/webserver-mangement layer?

@ssddanbrown commented on GitHub (May 5, 2022): Thanks for the information @whentotrade and @anonymous-gituser, Looks like the same line is tripping up both instances. This line, during my testing, does serve a purpose primarily for large attachment downloads to ensure that less memory is used. Most existing smaller attachments downloads should work without this line, but I'd rather find out why this is a problem in some environments. Could you both share further insight regarding your hosting environment? What linux distro and what exact version is it? What version of PHP are you using? What webserver are you using? Are you using some kind of hosting/webserver-mangement layer?
Author
Owner

@anonymous-gituser commented on GitHub (May 6, 2022):

Distro:
NAME="Ubuntu"
VERSION="21.04 (Hirsute Hippo)"

PHP:
7.4

webserver
Apache2

The host is a local VM - that does run another proprietary item, but shouldn't have any effect.

@anonymous-gituser commented on GitHub (May 6, 2022): Distro: NAME="Ubuntu" VERSION="21.04 (Hirsute Hippo)" PHP: 7.4 webserver Apache2 The host is a local VM - that does run another proprietary item, but shouldn't have any effect.
Author
Owner

@ssddanbrown commented on GitHub (May 6, 2022):

@anonymous-gituser Thanks for providing. Rare to see 21.04 in use, and it is out of support now, but just created an instance in a VM and set up a BookStack instance on Apache. Attachment downloads worked fine though. Might be something more nuanced.

Some exact versions for reference:

php -v
PHP 7.4.16 (cli) (built: Nov 25 2021 21:36:47) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.16, Copyright (c), by Zend Technologies

apache2 -v
Server version: Apache/2.4.46 (Ubuntu)
Server built:   2022-01-05T14:38:48

hostnamectl
...
Operating System: Ubuntu 21.04
Kernel: Linux 5.11.0-49-generic
Architecture: x86-64
@ssddanbrown commented on GitHub (May 6, 2022): @anonymous-gituser Thanks for providing. Rare to see 21.04 in use, and it is out of support now, but just created an instance in a VM and set up a BookStack instance on Apache. Attachment downloads worked fine though. Might be something more nuanced. Some exact versions for reference: ``` php -v PHP 7.4.16 (cli) (built: Nov 25 2021 21:36:47) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.16, Copyright (c), by Zend Technologies apache2 -v Server version: Apache/2.4.46 (Ubuntu) Server built: 2022-01-05T14:38:48 hostnamectl ... Operating System: Ubuntu 21.04 Kernel: Linux 5.11.0-49-generic Architecture: x86-64 ```
Author
Owner

@whentotrade commented on GitHub (May 6, 2022):

webserver running on latest linux, I dont know the exact distro.

PHP config:

PHP Version 7.4.29
image

@whentotrade commented on GitHub (May 6, 2022): webserver running on latest linux, I dont know the exact distro. PHP config: PHP Version 7.4.29 <img width="775" alt="image" src="https://user-images.githubusercontent.com/30272473/167076542-5abc229a-6311-4de8-a188-25e7c109845f.png">
Author
Owner

@ssddanbrown commented on GitHub (May 6, 2022):

Okay, Have done some further testing.
This can occur in environments where the PHP output_buffering option is disabled.
This is less common, although not invalid, in production environments.

I'll assign this to the next patch release to address so that we check buffer level before attempting to escape the default top-level buffer.

As a potential workaround, you could enable buffering by adding (Or editing the existing variable if existing) something like

output_buffering = 4096

within your php.ini file.

@ssddanbrown commented on GitHub (May 6, 2022): Okay, Have done some further testing. This can occur in environments where the PHP `output_buffering` option is disabled. This is less common, although not invalid, in production environments. I'll assign this to the next patch release to address so that we check buffer level before attempting to escape the default top-level buffer. As a potential workaround, you could enable buffering by adding (Or editing the existing variable if existing) something like ```ini output_buffering = 4096 ``` within your `php.ini` file.
Author
Owner

@whentotrade commented on GitHub (May 8, 2022):

@ssddanbrown Thanks for your research and testing. I can confirm that the workaround setting the output_buffering in the php.ini solved this issue. Thank you.

@whentotrade commented on GitHub (May 8, 2022): @ssddanbrown Thanks for your research and testing. I can confirm that the workaround setting the `output_buffering` in the php.ini solved this issue. Thank you.
Author
Owner

@ssddanbrown commented on GitHub (May 9, 2022):

@whentotrade Thanks for confirming the solution.

I have updated the logic in 2a99e23e6d to handle environments where output buffering is disabled. This will be part of our next patch release.

@ssddanbrown commented on GitHub (May 9, 2022): @whentotrade Thanks for confirming the solution. I have updated the logic in 2a99e23e6d2dfa8898eb7e2a9be97cbe9b819b2c to handle environments where output buffering is disabled. This will be part of our next patch release.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/BookStack#2778