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() for a non-seekable body whose reported stream position (from tell()) is negative or greater than its reported size (getSize()). The handler computes the sendable bytes as size minus position for non-seekable streams, so an out-of-range position makes that computation meaningless and is rejected as corrupt body metadata.
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 9b200fc580)
Solutions
- Switch to a seekable stream so the handler uses getSize() directly and never consults tell().
- Rewind the body ($body->rewind()) before dispatch so position is 0 and within size.
- Fix the custom StreamInterface so tell() always returns a value in [0, getSize()].
- Use Psr7\Utils::streamFor() over the raw resource so position/size stay consistent.
Example fix
// before: broken decorator
class MyStream implements StreamInterface {
public function tell(): int { return 9999; }
public function getSize(): ?int { return 100; }
}
// after
public function tell(): int { return ftell($this->resource); } Defensive patterns
Strategy: validation
Validate before calling
// For non-seekable bodies, verify position is within size.
$body = $request->getBody();
if (!$body->isSeekable()) {
try {
$pos = $body->tell();
$size = $body->getSize();
if ($size !== null && ($pos < 0 || $pos > $size)) {
throw new \LogicException('Body position out of range');
}
} catch (\RuntimeException $e) { /* tell() unavailable: framing will treat as unknown */ }
} Prevention
- Prefer seekable streams so the handler uses getSize() without consulting tell().
- Rewind bodies before dispatch so the position starts at 0.
- Unit-test custom StreamInterface decorators: tell() must stay within [0, getSize()].
When it happens
Trigger: Attaching a custom StreamInterface whose tell() returns a value greater than getSize(), or a negative position; a non-seekable wrapper that advances past its reported size without updating it; a bug in a third-party stream decorator that misreports position.
Common situations: Custom stream decorators (FnStream, caching streams) with broken tell()/getSize(); streams backed by resources whose fstat-based size is stale after the file was truncated; using a stream that was already read to EOF without rewinding.
Related errors
- Request body stream returned more bytes than requested
- Length parameter cannot be negative
- Content-Length does not match the request body size
- Request body ended before the declared Content-Length was re
- Cannot seek a stream while tracking encoded response bytes
AI-assisted analysis of guzzle/guzzle@9b200fc580 (2026-08-04).
Data as JSON: /data/errors/1cebd87d8b27b88d.json.
Report an issue: GitHub.