PHPOffice/PHPWord · error · PhpOffice\PhpWord\Exception\Exception
The archive failed to load with the following error code…
Error message
The archive failed to load with the following error code: $openStatus
What it means
After the file-existence check, XMLReader::getDomFromZip() calls ZipArchive::open(). If it returns anything other than true (an integer ZipArchive error code such as ER_READ=5, ER_NOZIP=19, ER_INCONS=21), further ZipArchive calls would fatal, so the library throws with the numeric error code embedded in the message.
Solutions
- Decode the numeric code in the message (e.g. 19 = ZipArchive::ER_NOZIP, 21 = ER_INCONS) to identify the cause.
- Validate the archive before use: $z=new ZipArchive(); $z->open($path)===true, or check it's a real OOXML file (finfo mime zip + presence of [Content_Types].xml).
- Re-upload/re-download the file if truncated or corrupt; reject legacy .doc files and use the appropriate reader.
- Check file permissions and disk space if the file is a valid zip.
Example fix
// before
$zip = new ZipArchive();
$status = $zip->open($path); // returns 19, later fatal
// after
$zip = new ZipArchive();
$status = $zip->open($path);
if ($status !== true) {
throw new RuntimeException("Corrupt or non-zip document ($status): $path");
} Defensive patterns
Strategy: try-catch
Validate before calling
$zip = new ZipArchive();
if ($zip->open($path) !== true) {
throw new InvalidArgumentException("Not a readable zip archive: $path");
}
$zip->close(); Try / catch
try {
$reader->getDomFromZip($zipFile, $xmlFile);
} catch (\PhpOffice\PhpWord\Exception\Exception $e) {
if (str_contains($e->getMessage(), 'failed to load with the following error code')) {
$code = (int) filter_var($e->getMessage(), FILTER_SANITIZE_NUMBER_INT);
throw new RuntimeException("Corrupt/non-zip document (ZipArchive code $code): $zipFile", $code, $e);
}
throw $e;
} Prevention
- Validate zip integrity with ZipArchive::open before processing user-supplied files
- Detect actual file type via finfo rather than trusting extensions
- Check uploads for completeness (size, checksum) at ingestion
- Verify disk space and permissions when archives fail intermittently
When it happens
Trigger: getDomFromZip() given a file that exists but is not a valid zip: old binary .doc saved as .docx, truncated download, password-protected zip, empty/corrupt archive, or a file without read permission (ZipArchive can stat but not open it).
Common situations: Users renaming legacy .doc to .docx; interrupted uploads; encrypted office files; disk full or permissions preventing ZipArchive from reading; corrupted templates in storage.
Related errors
- The filename ' . $sFileName . ' is not recognised as an OLE…
- Cannot find archive file.
- Could not close zip file.
- Invalid value, on of ' . implode(', ', $position) . '…
- Invalid value, on of ' . implode(', ', $restartNumbers) . '…
AI-assisted analysis of PHPOffice/PHPWord@aef95c0415 (2026-09-14).
Data as JSON: /api/errors/15c4f63e6ef81f39.
Report an issue: GitHub.
Appendix: source
Thrown at src/PhpWord/Shared/XMLReader.php:71
* @param string $zipFile
* @param string $xmlFile
*
* @return DOMDocument|false
*/
public function getDomFromZip($zipFile, $xmlFile)
{
if (file_exists($zipFile) === false) {
throw new Exception('Cannot find archive file.');
}
$zip = new ZipArchive();
$openStatus = $zip->open($zipFile);
if ($openStatus !== true) {
/**
* Throw an exception since making further calls on the ZipArchive would cause a fatal error.
* This prevents fatal errors on corrupt archives and attempts to open old "doc" files.
*/
throw new Exception("The archive failed to load with the following error code: $openStatus");
}
$content = $zip->getFromName(ltrim($xmlFile, '/'));
$zip->close();
if ($content === false) {
return false;
}
return $this->getDomFromString($content);
}
/**
* Get DOMDocument from content string.
*
* @param string $content
*
* @return DOMDocumentView on GitHub (pinned to aef95c0415)