Intervention/image · error · Intervention\Image\Exceptions\StreamException

Failed to build stream from string

Error message

Failed to build stream from string

What it means

buildStreamOrFail() (src/Traits/CanBuildStream.php) turns string input into a PHP stream by copying it into a php://temp handle. This StreamException means fopen('php://temp', 'r+') itself returned false, so the stream could not even be created before any data was written. It is essentially an environment-level failure (memory/temp capacity or a broken PHP runtime), not an input-format problem.

Source

Thrown at src/Traits/CanBuildStream.php:29

{
    /**
     * Transform the provided data into a stream resource with the data as its content.
     *
     * @param resource|string|null $data
     * @throws InvalidArgumentException
     * @throws StreamException
     * @return resource
     */
    public static function buildStreamOrFail(mixed $data = null)
    {
        $buildStrategy = match (true) {
            is_null($data) => fn(mixed $data) => fopen('php://temp', 'r+'),
            is_resource($data) && get_resource_type($data) === 'stream' => fn(mixed $data) => $data,
            is_string($data) => function (mixed $data) {
                $stream = fopen('php://temp', 'r+');

                if ($stream === false) {
                    throw new StreamException('Failed to build stream from string');
                }

                fwrite($stream, $data);
                return $stream;
            },
            default => throw new InvalidArgumentException(
                'Unable to create stream from ' . gettype($data) . '. Use only null, string or resource.',
            ),
        };

        $stream = $buildStrategy($data);

        if ($stream === false) {
            throw new StreamException('Failed to build stream');
        }

        $rewind = rewind($stream);

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Raise PHP's memory_limit (ini_set('memory_limit', '512M'); or php.ini/FPM pool config) and retry with the same input.
  2. Free memory before the call: unset() large buffers, avoid holding all images of a batch in memory, process one at a time.
  3. Check disk space on the temp filesystem (df -h /tmp) since php://temp falls back to a temp file; clear space or point sys_temp_dir elsewhere.
  4. Catch Intervention\Image\Exceptions\StreamException around the operation and report the environment problem instead of letting it fatal.

Example fix

// before
ini_set('memory_limit', '128M');
$stream = $manager->read($hugeBinaryString)->toGif(); // StreamException on tight limits

// after
ini_set('memory_limit', '512M');
$stream = $manager->read($hugeBinaryString)->toGif();
Defensive patterns

Strategy: try-catch

Validate before calling

if (strlen($binary) > ini_get('memory_limit') === false) { /* size sanity check */ }
// pragmatic pre-check:
$limit = ini_parse_quantity(ini_get('memory_limit')) ?: 128 * 1024 * 1024;
if (strlen($binary) > $limit / 4) {
    ini_set('memory_limit', (string) (strlen($binary) * 8));
}

Try / catch

try {
    $result = $image->toJpeg(); // or any stream-building encode
} catch (\Intervention\Image\Exceptions\StreamException $e) {
    // environment failure (memory/temp) - raise limits, free memory, then retry once
    ini_set('memory_limit', '512M');
    $result = $image->toJpeg();
}

Prevention

When it happens

Trigger: Calling a stream-backed API with a large string where the PHP process cannot allocate the php://temp handle: e.g. $image->toJpeg() / toStream()-style encode paths (AbstractEncoder uses this trait) or ImageManager::read($binaryString) on a big buffer while memory_limit is nearly exhausted. Also possible when the system temp directory is full, since php://temp spills to disk after the memory threshold.

Common situations: Shared hosting with a tight memory_limit (e.g. 64M/128M) while processing multi-megapixel photos; batch jobs that keep many image strings in memory; containers with a full /tmp volume (php://temp spills there); rare misconfigured PHP builds.

Related errors


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