PHPOffice/PhpSpreadsheet · error · ReaderException
Could not open file $filename for reading.
Error message
Could not open file $filename for reading.
What it means
Csv::loadSpreadsheetFromString() funnels the string into a data://text/plain URI and fopen()s it. If fopen of the data:// wrapper fails, the reader throws this. The dominant cause is allow_url_fopen=Off (a common hardening setting), which disables the URL-style stream wrappers including data://.
Source
Thrown at src/PhpSpreadsheet/Reader/Csv.php:361
}
public function castFormattedNumberToNumeric(
bool $castFormattedNumberToNumeric,
bool $preserveNumericFormatting = false
): void {
$this->castFormattedNumberToNumeric = $castFormattedNumberToNumeric;
$this->preserveNumericFormatting = $preserveNumericFormatting;
}
/**
* Open data uri for reading.
*/
private function openDataUri(string $filename): void
{
$fileHandle = fopen($filename, 'rb');
if ($fileHandle === false) {
// @codeCoverageIgnoreStart
throw new ReaderException('Could not open file ' . $filename . ' for reading.');
// @codeCoverageIgnoreEnd
}
$this->fileHandle = $fileHandle;
}
/**
* Loads PhpSpreadsheet from file into PhpSpreadsheet instance.
*/
public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet): Spreadsheet
{
return $this->loadStringOrFile($filename, $spreadsheet, false);
}
/**
* Loads PhpSpreadsheet from file into PhpSpreadsheet instance.
*/
private function loadStringOrFile(string $filename, Spreadsheet $spreadsheet, bool $dataUri): SpreadsheetView on GitHub (pinned to 65b080eef4)
Solutions
- Enable allow_url_fopen (php.ini, or ini_set('allow_url_fopen', '1') at runtime where the host permits it)
- If you cannot change ini settings, bypass the string API: write the content to a temporary file and call load() instead
- Check the setting in deployment smoke tests wherever string loading is used
Example fix
// before
$spreadsheet = (new Csv())->loadSpreadsheetFromString($csvText); // allow_url_fopen=Off -> throws
// after
if (filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOL)) {
$spreadsheet = (new Csv())->loadSpreadsheetFromString($csvText);
} else {
$tmp = tempnam(sys_get_temp_dir(), 'csv');
file_put_contents($tmp, $csvText);
$spreadsheet = (new Csv())->load($tmp);
unlink($tmp);
} Defensive patterns
Strategy: fallback
Validate before calling
if (!filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOL)) {
// string API unavailable — use the temp-file route below instead of calling it
} Try / catch
try {
$spreadsheet = (new Csv())->loadSpreadsheetFromString($text);
} catch (ReaderException $e) {
$tmp = tempnam(sys_get_temp_dir(), 'csv');
file_put_contents($tmp, $text);
$spreadsheet = (new Csv())->load($tmp); // fallback path
unlink($tmp);
} Prevention
- Assert allow_url_fopen in deployment checks wherever string loading is used
- Default to the temp-file pattern for string content in hardened environments
- Document the ini requirement next to any loadSpreadsheetFromString call
When it happens
Trigger: Calling $reader->loadSpreadsheetFromString($csv) on any server where allow_url_fopen is disabled (php.ini hardening, managed hosting, strict container defaults); the string API works locally but explodes only in production.
Common situations: Code that loads CSV/HTML from strings (API payloads, DB blobs, scraped content) moving from a dev machine to a hardened production host.
Related errors
- $filename is an Invalid Spreadsheet file.
- Unable to get contents of $filename
- Unable to open php://memory
- Unable to open stream $path
- Invalid protocol for linked drawing
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/500365ec9fa51d92.
Report an issue: GitHub.