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

  1. Switch to a seekable stream so the handler uses getSize() directly and never consults tell().
  2. Rewind the body ($body->rewind()) before dispatch so position is 0 and within size.
  3. Fix the custom StreamInterface so tell() always returns a value in [0, getSize()].
  4. 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

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


AI-assisted analysis of guzzle/guzzle@9b200fc580 (2026-08-04). Data as JSON: /data/errors/1cebd87d8b27b88d.json. Report an issue: GitHub.