{"id":"71c467f405249553","repo":"guzzle/guzzle","slug":"failed-while-transferring-the-response-body","errorCode":null,"errorMessage":"Failed while transferring the response body","messagePattern":"Failed while transferring the response body","errorType":"exception","errorClass":"GuzzleHttp\\Exception\\ResponseTransferException","httpStatus":null,"severity":"error","filePath":"src/Handler/StreamHandler.php","lineNumber":710,"sourceCode":"                // that number of bytes has been read. This can prevent infinitely\n                // reading from a stream when dealing with servers that do not\n                // honor Connection: Close headers.\n                $copied = Psr7\\Utils::copyToStream($source, $target, $copyLimit);\n            } catch (ResponseException $e) {\n                throw $e;\n            } catch (TimeoutException $e) {\n                throw new ResponseTimeoutException(\n                    'Timed out while transferring the response body',\n                    $request,\n                    $response,\n                    $e\n                );\n            } catch (\\OverflowException $e) {\n                throw new ResponseException($e->getMessage(), $request, $response, $e);\n            } catch (\\Exception $e) {\n                // Any other response-body transfer failure surfaces as a\n                // ResponseTransferException carrying the response.\n                throw new ResponseTransferException(\n                    $e->getMessage() !== '' ? $e->getMessage() : 'Failed while transferring the response body',\n                    $request,\n                    $response,\n                    $e\n                );\n            }\n\n            $receivedLength = $encodedBody !== null ? $encodedBody->getBytesRead() : $copied;\n            if ($declaredLength !== null && $receivedLength < $declaredLength) {\n                throw new ResponseTransferException(\n                    'Response body ended before the declared Content-Length was reached',\n                    $request,\n                    $response\n                );\n            }\n\n            try {\n                if ($sink->isSeekable()) {","sourceCodeStart":692,"sourceCodeEnd":728,"githubUrl":"https://github.com/guzzle/guzzle/blob/9b200fc5805036b331d6031199880dadecae0275/src/Handler/StreamHandler.php#L692-L728","documentation":"Thrown by StreamHandler::drain() when copying the response body fails with a generic exception that is neither a TimeoutException nor an OverflowException; if the underlying message is empty the default text 'Failed while transferring the response body' is used. It is wrapped as a ResponseTransferException carrying both request and response.","triggerScenarios":"The transport read fails partway through (broken pipe, connection reset, SSL read error) without matching a recognized timeout signature; a custom sink stream throws on write; the underlying resource is closed externally.","commonSituations":"Unstable networks dropping connections mid-download; intermediate proxies resetting the connection; disk-full or permission errors writing to a 'sink' file; resource exhaustion.","solutions":["Catch ResponseTransferException and retry with backoff (transient resets often succeed).","If using a 'sink' file, verify the destination is writable and has free disk space.","Check the underlying exception (getPrevious()) for the real OS-level error and address it.","For flaky endpoints, enable retry middleware or an idempotent retry policy."],"exampleFix":"// before\n$resp = $client->get($largeFileUrl); // fails mid-transfer\n// after\ntry {\n    $resp = $client->get($largeFileUrl);\n} catch (ResponseTransferException $e) {\n    // log $e->getPrevious() and retry with backoff\n}","handlingStrategy":"try-catch","validationCode":"// Pre-check the sink destination is writable before the transfer.\nif (is_string($options['sink'] ?? null) && !is_writable(dirname($options['sink']))) {\n    throw new \\RuntimeException('sink directory is not writable');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $response = $client->get($url);\n} catch (\\GuzzleHttp\\Exception\\ResponseTransferException $e) {\n    // inspect $e->getPrevious() for the OS-level cause; retry with backoff if transient\n}","preventionTips":["Verify 'sink' destinations are writable and have free disk space.","Use retry middleware with idempotent methods for flaky endpoints.","Log getPrevious() to distinguish resets from local I/O failures."],"tags":["stream-handler","response-body","network","transfer-error"],"analyzedSha":"9b200fc5805036b331d6031199880dadecae0275","analyzedAt":"2026-08-04T21:24:26.648Z","schemaVersion":2}