Intervention/image · error · InvalidArgumentException
Image source must be a resource of type 'file' or 'stream'
Error message
Image source must be a resource of type 'file' or 'stream'
What it means
StreamImageDecoder accepts only a PHP resource whose get_resource_type() is 'file' or 'stream'. Any other input (string, object, closed resource, or a resource of another type like a curl handle) triggers InvalidArgumentException before any reading starts.
Source
Thrown at src/Drivers/Gd/Decoders/StreamImageDecoder.php:43
return is_resource($input);
}
/**
* {@inheritdoc}
*
* @see DecoderInterface::decode()
*
* @throws InvalidArgumentException
* @throws StreamException
* @throws DriverException
* @throws StateException
* @throws ImageDecoderException
* @throws NotSupportedException
*/
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 = '';
$result = rewind($input);
if ($result === 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;
}
View on GitHub (pinned to 5598b9e397)
Solutions
- Pass a real resource from fopen($path, 'rb') or a php://temp handle
- For PSR-7 streams, use (string) $stream or $stream->getContents() and read the string instead
- For plain strings, call $manager->read($string) and let BinaryImageDecoder handle it
Example fix
// before
$image = $manager->decodeStream($response->getBody()); // object, not resource
// after
$stream = fopen('php://temp', 'rb+');
fwrite($stream, $response->getBody()->getContents());
rewind($stream);
$image = $manager->decodeStream($stream);
// or simply: $image = $manager->read($response->getBody()->getContents()); Defensive patterns
Strategy: type-guard
Validate before calling
if (!is_resource($stream) || !in_array(get_resource_type($stream), ['file', 'stream'], true)) {
throw new InvalidArgumentException('Expected a file/stream resource');
}
$manager->decodeStream($stream); Type guard
function isFileStream(mixed $value): bool
{
return is_resource($value) && in_array(get_resource_type($value), ['file', 'stream'], true);
} Try / catch
try {
$image = $manager->decodeStream($source);
} catch (InvalidArgumentException $e) {
$image = $manager->read((string) $source); // fall back to string decoding
} Prevention
- Convert PSR-7/framework stream objects to strings or php://temp first
- Never pass curl or proc handles as image sources
- Use $manager->read() for strings and paths
When it happens
Trigger: $manager->decodeStream($psr7Stream) where $psr7Stream is a PSR-7 StreamInterface object; passing a curl handle; passing a resource already closed by fclose(); passing a plain string path.
Common situations: Confusing Guzzle/Symfony stream objects with native PHP resources, frameworks whose file APIs return objects (Symfony UploadedFile), resources from proc_open or curl reused as image sources.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- Image source must be of type SplFileInfo
- Failed to rewind position of stream
- Failed to read image from stream
- Failed to decode image from stream, could be unsupported ima
- Color object must be of type {ColorInterface::class}
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/0d32ab8231f2cdff.
Report an issue: GitHub.