PHPOffice/PhpSpreadsheet · error · ReaderException
Unable to open php://memory
Error message
Unable to open php://memory
What it means
After re-encoding a non-UTF-8 file to UTF-8, the Csv reader stores the converted bytes in a php://memory stream. fopen('php://memory') failing means the process could not allocate that memory block — in practice, memory_limit is nearly exhausted by a large input file (converted copy roughly the size of the file). Upstream marks it @codeCoverageIgnore because it is essentially unreachable except under memory pressure.
Source
Thrown at src/PhpSpreadsheet/Reader/Csv.php:317
if ($this->inputEncoding === self::GUESS_ENCODING) {
$this->inputEncoding = self::guessEncoding($filename, $this->fallbackEncoding);
}
$this->openFile($filename);
if ($this->inputEncoding !== 'UTF-8') {
$this->convertNonUtf8($filename);
}
}
protected function convertNonUtf8(string $filename): void
{
fclose($this->fileHandle);
$entireFile = file_get_contents($filename);
if ($entireFile === false) {
throw new ReaderException("Unable to get contents of $filename"); // @codeCoverageIgnore
}
$fileHandle = fopen('php://memory', 'r+b');
if ($fileHandle === false) {
throw new ReaderException('Unable to open php://memory'); // @codeCoverageIgnore
}
$this->fileHandle = $fileHandle;
$data = StringHelper::convertEncoding($entireFile, 'UTF-8', $this->inputEncoding);
fwrite($this->fileHandle, $data);
$this->skipBOM();
}
public function setTestAutoDetect(bool $value): self
{
$this->testAutodetect = $value;
return $this;
}
private function setAutoDetect(?string $value, int $version = PHP_VERSION_ID): ?string
{
$retVal = null;
if ($value !== null && $this->testAutodetect && $version < 90000) {View on GitHub (pinned to 65b080eef4)
Solutions
- Raise memory_limit (ini_set or php.ini -d) to comfortably exceed the file size
- Pre-convert the file to UTF-8 externally (iconv -f cp1252 -t utf-8) so convertNonUtf8() is never entered
- Split oversized files into chunks and load them incrementally
Example fix
// before
ini_set('memory_limit', '128M');
$spreadsheet = (new Csv())->load('huge-latin1.csv'); // memory stream alloc fails
// after
ini_set('memory_limit', '1G');
$spreadsheet = (new Csv())->load('huge-latin1.csv');
// or better: iconv -f cp1252 -t utf-8 huge-latin1.csv > huge-utf8.csv, then load that Defensive patterns
Strategy: validation
Validate before calling
function bytesFromShorthand(string $v): int { $u = strtolower(substr($v, -1)); $n = (int) $v; return match ($u) { 'g' => $n * 1024 ** 3, 'm' => $n * 1024 ** 2, 'k' => $n * 1024, default => (int) $v }; }
$headroom = bytesFromShorthand(ini_get('memory_limit')) - memory_get_usage(true);
if (filesize($file) * 2 > $headroom) {
ini_set('memory_limit', ceil(filesize($file) * 3 / 1048576) . 'M');
} Prevention
- Budget roughly 2-3× file size of memory for non-UTF-8 CSV loads
- Pre-convert encodings with iconv at the CLI so the reader's memory-stream path never runs
- Chunk very large imports instead of loading whole files
When it happens
Trigger: Loading a large non-UTF-8 CSV (tens/hundreds of MB) with a tight memory_limit; memory already consumed by earlier payloads in the same request before the reader runs.
Common situations: Batch imports on shared hosting with memory_limit=128M; containers with hard memory caps; legacy latin1/cp1252 exports from ERP systems.
Related errors
- Unable to get contents of $filename
- Code page $codePage not implemented on this system.
- Could not open file {filename} for reading.
- $filename is an Invalid Spreadsheet file.
- Could not open file $filename for reading.
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/57939d623ef75451.
Report an issue: GitHub.