PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
{filename} is an Invalid HTML file.
Error message
{filename} is an Invalid HTML file. What it means
The Html reader's loadIntoExisting() guards itself with canRead(), which sniffs for recognizable HTML markup. When the check fails it throws 'Invalid HTML file' before DOM parsing starts — the content does not look like HTML to the reader's heuristic.
Source
Thrown at src/PhpSpreadsheet/Reader/Html.php:797
}
// simply append the text if the cell content is a plain text string
$cellContent .= $domText;
// but if we have a rich text run instead, we need to append it correctly
// TODO
} elseif ($child instanceof DOMElement) {
$this->processDomElementBody($sheet, $row, $column, $cellContent, $child);
}
}
}
/**
* Loads PhpSpreadsheet from file into PhpSpreadsheet instance.
*/
public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet): Spreadsheet
{
// Validate
if (!$this->canRead($filename)) {
throw new Exception($filename . ' is an Invalid HTML file.');
}
// Create a new DOM object
$dom = new DOMDocument();
// Reload the HTML file into the DOM object
if (is_bool($this->suppressLoadWarnings)) {
$useErrors = libxml_use_internal_errors($this->suppressLoadWarnings);
} else {
$useErrors = null;
}
try {
$convert = $this->getSecurityScannerOrThrow()->scanFile($filename);
$convert = static::replaceNonAsciiIfNeeded($convert);
$loaded = ($convert === null) ? false : $dom->loadHTML($convert);
} catch (Throwable $e) {
$loaded = false;View on GitHub (pinned to 65b080eef4)
Solutions
- Use IOFactory::identify() and the matching reader instead of hardcoding Html
- If the file must be HTML, verify the leading bytes contain real markup (e.g. str_contains strtolower for '<html' or '<table') before loading
- Convert .mht to plain .html (open in a browser or mail client and re-save) before import
Example fix
// before
$spreadsheet = (new Html())->loadIntoExisting('export.mht', $spreadsheet); // MHT not recognized -> throws
// after
$type = IOFactory::identify($uploadPath);
$reader = IOFactory::createReader($type);
$spreadsheet = $reader->loadIntoExisting($uploadPath, $spreadsheet); Defensive patterns
Strategy: validation
Validate before calling
$head = substr((string) file_get_contents($filename), 0, 2048);
if (!str_contains(strtolower($head), '<')) {
throw new RuntimeException('File contains no HTML markup');
}
$spreadsheet = (new Html())->loadIntoExisting($filename, $spreadsheet); Prevention
- Check for markup markers before invoking the Html reader
- Convert .mht exports to plain HTML prior to import
- Route unknown files through IOFactory::identify()
When it happens
Trigger: loadIntoExisting() on a file that is actually plain text, JSON, XML, or empty; Excel's 'Single File Web Page' (.mht) exports, which the HTML reader cannot recognize; files whose markup is buried after large non-markup preamble so the sniff misses it.
Common situations: Feeding scraped or API-returned content saved as .html; user uploads validated only by extension; importing mail-exported .mht files.
Related errors
- $filename is an Invalid Spreadsheet file.
- {filename} is an invalid Gnumeric file.
- {filename} is an Invalid SYLK file.
- Failed to load file {filename} as a DOM Document
- Failed to load content as a DOM Document
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/362817ec337e8302.
Report an issue: GitHub.