Intervention/image · error · StreamException

Failed to read image from stream

Error message

Failed to read image from stream

What it means

fread() returned false while the decoder drained the stream in 1024-byte chunks - an actual read error mid-stream (socket reset, TLS failure, wrapper error), distinct from a clean EOF which ends the loop normally. Thrown as StreamException before any image decoding is attempted.

Source

Thrown at src/Drivers/Imagick/Decoders/StreamImageDecoder.php:52

     * @throws DriverException
     * @throws StateException
     */
    public function decode(mixed $input): ImageInterface
    {
        if (!is_resource($input) || !in_array(get_resource_type($input), ['file', 'stream'])) {
            throw new InvalidArgumentException('Image source must be a resource of type "file" or "stream"');
        }

        $contents = '';
        $rewind = rewind($input);
        if ($rewind === false) {
            throw new StreamException('Failed to rewind position of stream');
        }

        while (!feof($input)) {
            $chunk = fread($input, 1024);
            if ($chunk === false) {
                throw new StreamException('Failed to read image from stream');
            }

            $contents .= $chunk;
        }

        try {
            return parent::decode($contents);
        } catch (DecoderException) {
            throw new ImageDecoderException(
                'Failed to decode image from stream, could be unsupported image format',
            );
        }
    }
}

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Fetch the full body with an HTTP client that verifies completeness (Content-Length check) and pass the string
  2. Inspect stream_get_meta_data($input) for 'timed_out' and wrapper data to find the underlying cause
  3. Raise default_socket_timeout or the wrapper's timeout option for slow sources
  4. Retry the fetch - transient network resets are common

Example fix

// before
$image = $manager->read(fopen('https://slow.example.com/big.jpg', 'rb'));

// after
$response = $httpClient->request('GET', 'https://slow.example.com/big.jpg', ['timeout' => 30]);
$image = $manager->read($response->getContent());
Defensive patterns

Strategy: retry

Validate before calling

$meta = stream_get_meta_data($stream);
if (!empty($meta['timed_out'])) {
    throw new RuntimeException('Stream timed out mid-read');
}

Try / catch

try {
    $image = $manager->read($stream);
} catch (\Intervention\Image\Exceptions\StreamException $e) {
    // transient network failure: close, re-open, retry once with backoff
}

Prevention

When it happens

Trigger: A network stream (fopen('https://...')) where the server drops the connection mid-body; S3/FTP stream wrappers whose credentials expire or time out during transfer; a stream left in an error state by a prior operation.

Common situations: Remote image fetching with unreliable sources; default_socket_timeout too low for slow origins; partial uploads read from php://input before the body fully arrived.

Related errors


AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23). Data as JSON: /api/errors/cfe530a0cb978108. Report an issue: GitHub.