Appwrite Framework Bug: Large File Downloads Fail, Exposing Critical Swoole 6 Incompatibility
A critical bug in the Appwrite open-source backend framework is causing large file downloads to fail, exposing a deeper incompatibility with the latest Swoole runtime. When users attempt to download files larger than 20 MB through standard browsers or wget, the transfer stalls, showing 0 bytes and never completing. This failure mode creates a direct barrier for applications relying on Appwrite for file storage and delivery, forcing users to employ workarounds like download managers that use Range requests.
The root cause is traced to a specific method within the Utopia HTTP response layer. The framework's `chunk()` method, designed to stream data, incorrectly calls header-appending logic on every loop iteration. After the first data packet is sent via Swoole's `write()` function, the HTTP headers are considered finalized. In the updated Swoole 6 environment, any subsequent attempt to modify headers or status—a side effect of the flawed `chunk()` loop—triggers a Throwable error. This error is silently caught by the overarching HTTP request handler, which then terminates the connection prematurely, resulting in the corrupted 0-byte downloads. The bug selectively spares download managers because they utilize a different code path (`$response->send()`) that correctly appends headers only once.
The proposed fix involves modifying the core `Appwrite\Utopia\Response` class to introduce a state flag, ensuring header and cookie logic fires only on the initial chunk. This patch is not merely a feature fix but a necessary adaptation to Swoole's stricter runtime enforcement in version 6. The incident highlights the fragility of streaming implementations in modern PHP frameworks and serves as a warning for other projects migrating to Swoole 6, where assumptions about mid-response header manipulation can break core functionality without clear error reporting to the end-user.