guzzle/guzzle · error · GuzzleHttp\Exception\RequestException
The request body position is outside the stream size
Error message
The request body position is outside the stream size
What it means
Thrown by RequestFraming::bodySize() as a RequestException when a non-seekable body stream's tell() reports a position that is negative or greater than the stream's total size. The available byte count is computed as size - position; an out-of-range position makes that meaningless, so the handler rejects it before dispatch.
Solutions
- Use a seekable stream (e.g. GuzzleHttp\Psr7\Utils::streamFor($string)) so position is handled by rewind.
- Fix the custom stream's tell() and getSize() to return consistent, monotonic values.
- Wrap the body in a buffered stream and reset its position to 0 before assigning.
- If the source is php://input or a pipe, read it fully into a seekable buffer first.
Example fix
// before
$request = new Request('POST', '/u', [], $brokenNonSeekableStream); // tell() > size
// after
$buffer = \GuzzleHttp\Psr7\Utils::streamFor((string) $brokenNonSeekableStream);
$request = new Request('POST', '/u', [], $buffer); Defensive patterns
Strategy: validation
Validate before calling
$body = $request->getBody();
if (!$body->isSeekable()) {
$size = $body->getSize();
try {
$pos = $body->tell();
} catch (\RuntimeException $e) {
$pos = null;
}
if ($pos !== null && ($pos < 0 || $pos > $size)) {
throw new \InvalidArgumentException('Body position is outside the stream size');
}
} Type guard
function bodyPositionIsConsistent(\Psr\Http\Message\StreamInterface $s): bool {
if ($s->isSeekable()) {
return true;
}
try {
$pos = $s->tell();
} catch (\RuntimeException $e) {
return true;
}
return $pos >= 0 && $pos <= $s->getSize();
} Prevention
- Use seekable streams for request bodies
- Wrap pipes/inputs in a buffered seekable stream
- Keep custom StreamInterface tell()/getSize() consistent and monotonic
When it happens
Trigger: A request body that is a non-seekable stream whose current position is inconsistent with its reported size (position < 0 or position > size). bodySize() reads tell() only for non-seekable streams and validates the range.
Common situations: A custom StreamInterface that returns inconsistent tell()/getSize(), a pipe/socket stream whose position accounting is broken, or a stream that was partially consumed and rewound incorrectly. Bugs in a decorated stream wrapper.
Related errors
- Content-Length does not match the request body size
- Request body size must not be negative
- An unknown-size HTTP/1.0 request body requires…
- Invalid Content-Length request header:
- Unsupported Transfer-Encoding request header
AI-assisted analysis of guzzle/guzzle@d1cbca7697 (2026-08-06).
Data as JSON: /api/errors/1cebd87d8b27b88d.
Report an issue: GitHub.
Appendix: source
Thrown at src/Handler/RequestFraming.php:162
$request,
$e,
'Timed out while determining the request body size',
'Failed to determine the request body size'
);
}
if ($seekable) {
return $size;
}
try {
$position = $body->tell();
} catch (\RuntimeException $e) {
return null;
}
if ($position < 0 || $position > $size) {
throw new RequestException('The request body position is outside the stream size', $request);
}
return $size - $position;
}
/**
* Materializes the body, stopping at the selected Content-Length when
* present.
*
* @throws RequestException when the body cannot be fully rewound or read
*/
public function materialize(): string
{
$body = $this->request->getBody();
if ($this->contentLength === null) {
try {
return (string) $body;View on GitHub (pinned to d1cbca7697)