Skip to content

Calling detach() on non-seekable stream raises fatal error #630

@alex-patterson-webdev

Description

@alex-patterson-webdev

PHP version: x.y.z (hint: php --version)

8.4

Description

When calling GuzzleHttp\Psr7\Stream::detach(), on a NON seekable stream resource (tcp_socket/ssl) a PHP Fatal error is raised.

Fatal error: Uncaught TypeError: ftell(): supplied resource is not a valid stream resource in /var/www/.../vendor/guzzlehttp/psr7/src/Stream.php:129

How to reproduce

$client = new Client(
    [
        'timeout' => 0,
        'connect_timeout' => 0,
        'verify' => false,
        'http_errors' => true,
    ]
);

// Should be 72.19 MB
$response = $client->get('http://192.168.7.106/DCIM/Movie/2025_0829_193501_033803F.MP4', ['stream' => true]);

/**
 * Fatal error: Uncaught TypeError: ftell(): 
 * supplied resource is not a valid stream resource in /var/www/..../vendor/guzzlehttp/psr7/src/Stream.php:129
 */
$resource = $response->getBody()->detach();

Possible Solution

Remove the calls to ftekk(), feof($result) and stream_get_meta_data() from the end of Stream::detach() for non-seekable resources.

    public function detach()
    {
        if (!isset($this->stream)) {
            return null;
        }

        $result = $this->stream;
        unset($this->stream);
        $this->size = $this->uri = null;
        $this->readable = $this->writable = $this->seekable = false;

        //$tell = ftell($result);
        //$eof = feof($result);
        //$md = stream_get_meta_data($result);

        return $result;
    }

Additional context

I must have access to the raw PHP resource as the consuming library does not accept a PSR7 StreamInterface.

By commenting out the above lines detach() returns the expected raw resource.

$resource = $response->getBody()->detach();
$metadata = stream_get_meta_data($resource);

/*
Array
(
    [timed_out]    => false
    [blocked]      => 1
    [eof]          => false
    [wrapper_data] => Array
        (
            [0] => HTTP/1.1 200 OK
            [1] => Server: hfs/1.00.000
            [2] => Cache-Control: no-store, no-cache, must-revalidate
            [3] => Pragma: no-cache
            [4] => Accept-Ranges: bytes
            [5] => Content-Length: 75694080
            [6] => Content-Type: application/octet-stream
            [7] => Connection: close
        )

    [wrapper_type] => http
    [stream_type]  => tcp_socket/ssl
    [mode]         => r
    [unread_bytes] => 0
    [seekable]     => false
    [uri]          => http://192.168.7.106/DCIM/Movie/2025_0829_193501_033803F.MP4
)
*/
print_r($metadata);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions