PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Reader\Exception
Could not open file {filename} for reading.
Error message
Could not open file {filename} for reading. What it means
BaseReader::openFile() first asserts the file exists, then attempts fopen($filename, 'rb'). The exception fires only when fopen fails after the existence check — i.e. the path exists but cannot be opened for reading by the PHP process.
Source
Thrown at src/PhpSpreadsheet/Reader/BaseReader.php:308
} catch (ReaderException $e) {
throw $e;
}
}
/**
* Open file for reading.
*/
protected function openFile(string $filename): void
{
$fileHandle = false;
if ($filename) {
File::assertFile($filename);
// Open file
$fileHandle = fopen($filename, 'rb');
}
if ($fileHandle === false) {
throw new ReaderException('Could not open file ' . $filename . ' for reading.');
}
$this->fileHandle = $fileHandle;
}
/**
* Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns).
*
* @return array<int, array{worksheetName: string, lastColumnLetter: string, lastColumnIndex: int, totalRows: int, totalColumns: int, sheetState: string}>
*/
public function listWorksheetInfo(string $filename): array
{
throw new PhpSpreadsheetException('Reader classes must implement their own listWorksheetInfo() method');
}
/**
* Returns names of the worksheets from a file,
* possibly without parsing the whole file to a Spreadsheet object.View on GitHub (pinned to 65b080eef4)
Solutions
- Verify with is_file() && is_readable() before calling load(), and fix ownership/permissions (chmod/chown) or copy the file to a location your process owns
- Ensure the configured path is a regular file, not a directory, and lies inside open_basedir
- For uploads, move_uploaded_file() into your own temp path with correct ownership before parsing
Example fix
// before
$spreadsheet = IOFactory::load('/uploads/report.xlsx'); // exists but unreadable -> throws
// after
if (!is_file($path) || !is_readable($path)) {
throw new RuntimeException("Input file missing or unreadable: $path");
}
$spreadsheet = IOFactory::load($path); Defensive patterns
Strategy: validation
Validate before calling
if (!is_string($path) || !is_file($path) || !is_readable($path)) {
throw new RuntimeException("Cannot read spreadsheet file: " . var_export($path, true));
}
$spreadsheet = IOFactory::load($path); Prevention
- Check is_file() && is_readable() before every load; catch permission problems with your own message
- Copy uploads to a temp file your process owns before parsing, avoiding races with cleanup jobs
- Verify open_basedir coverage for the storage path during deployment checks
When it happens
Trigger: No read permission on the file (chmod 600 owned by another user); the file is deleted or replaced between assertFile() and fopen() (tmp-cleanup race); open_basedir restrictions on the path; the path is actually a directory; a symlink pointing to an unreadable target.
Common situations: Uploaded files stored with root ownership then read by the web server user; cron jobs purging the temp dir while an import runs; deployment configs with restrictive open_basedir; paths built from configuration pointing at a directory.
Related errors
- Could not create temporary file
- $filename is an Invalid Spreadsheet file.
- Unable to get contents of $filename
- Unable to open php://memory
- Code page $codePage not implemented on this system.
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/5fbfcaadfaa883e9.
Report an issue: GitHub.