PHPOffice/PhpSpreadsheet · error · ReaderException

Unable to get contents of $filename

Error message

Unable to get contents of $filename

What it means

When the Csv reader's input encoding is not UTF-8, convertNonUtf8() re-reads the entire file with file_get_contents() to re-encode it. This exception fires if that read returns false — an environmental failure (the file vanished or became unreadable between the earlier fopen and this read), which is why upstream marks it @codeCoverageIgnore.

Source

Thrown at src/PhpSpreadsheet/Reader/Csv.php:313

            if ($encoding !== '') {
                $this->inputEncoding = $encoding;
            }
        }
        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;
    }

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Copy the upload to a temp file you control before loading, and load that copy
  2. Ensure nothing deletes or mutates the file while the reader runs (adjust tmp retention)
  3. Run 64-bit PHP for very large files

Example fix

// before
$spreadsheet = (new Csv())->load('/tmp/queue/incoming.csv'); // cleaner may unlink mid-load

// after
$stable = tempnam(sys_get_temp_dir(), 'csv');
copy($incomingPath, $stable);
$spreadsheet = (new Csv())->load($stable);
unlink($stable);
Defensive patterns

Strategy: validation

Validate before calling

if (!is_readable($filename)) {
    throw new RuntimeException("Input vanished or unreadable: $filename");
}
$stable = tempnam(sys_get_temp_dir(), 'csv');
copy($filename, $stable); // decouple from cleanup races
$spreadsheet = (new Csv())->load($stable);
unlink($stable);

Prevention

When it happens

Trigger: The file is deleted or its permissions change mid-request (temp-dir cleanup race); a 2GB+ file on a 32-bit PHP build where size handling fails; filesystem faults while the import runs.

Common situations: Long-running queue jobs parsing uploads stored in an aggressively cleaned tmp directory; files larger than PHP's integer handling on 32-bit deployments.

Related errors


AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17). Data as JSON: /api/errors/1397c9b598c914d1. Report an issue: GitHub.