PHPOffice/PHPWord · critical · PhpOffice\PhpWord\Exception\Exception

Could not close zip file.

Error message

Could not close zip file.

What it means

TemplateProcessor::save() writes all modified parts back into the temporary zip archive and then closes it. If ZipArchive::close() returns false the archive could not be finalized — typically because the temp file is not writable, the disk is full, or the file is locked. The saved document is invalid or missing.

Solutions

  1. Check disk space and write permissions on the temp/output directory (sys_get_temp_dir() and the saveAs target).
  2. Ensure the output file is not open/locked by another process or held by antivirus/sync software.
  3. Call saveAs($path) to a fully writable path instead of relying on the default temp location.
  4. Retry the save once with a fresh TemplateProcessor instance if it persists.

Example fix

// before
$path = $processor->save(); // fails on read-only /tmp
// after
$processor->saveAs('/var/www/writable/output.docx');
Defensive patterns

Strategy: try-catch

Validate before calling

function canSaveTo(string $dir): bool {
    return is_dir($dir) && is_writable($dir) && (disk_free_space($dir) === false || disk_free_space($dir) > 1024 * 1024);
}

Try / catch

try {
    $processor->saveAs($target);
} catch (\PhpOffice\PhpWord\Exception\Exception $e) {
    if (str_contains($e->getMessage(), 'Could not close zip file')) {
        error_log('Zip close failed: check disk space/locks on ' . $target);
        $processor = null; // rebuild template processor and retry
    } else { throw $e; }
}

Prevention

When it happens

Trigger: Calling save()/saveAs() when the temporary document file cannot be written: read-only temp directory, insufficient disk space, file locked by another process (e.g. opened in Word), or the ZipArchive is in an inconsistent state.

Common situations: Servers with a full /tmp or read-only storage after deployment changes; concurrent processing of the same template file; antivirus or file-sync tools (OneDrive/Dropbox) locking the output file on Windows.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of PHPOffice/PHPWord@aef95c0415 (2026-09-14). Data as JSON: /api/errors/0ffa390868ce551f. Report an issue: GitHub.

Appendix: source

Thrown at src/PhpWord/TemplateProcessor.php:1014

     */
    public function save()
    {
        foreach ($this->tempDocumentHeaders as $index => $xml) {
            $this->savePartWithRels($this->getHeaderName($index), $xml);
        }

        $this->savePartWithRels($this->getMainPartName(), $this->tempDocumentMainPart);
        $this->savePartWithRels($this->getSettingsPartName(), $this->tempDocumentSettingsPart);

        foreach ($this->tempDocumentFooters as $index => $xml) {
            $this->savePartWithRels($this->getFooterName($index), $xml);
        }

        $this->zipClass->addFromString($this->getDocumentContentTypesName(), $this->tempDocumentContentTypes);

        // Close zip file
        if (false === $this->zipClass->close()) {
            throw new Exception('Could not close zip file.'); // @codeCoverageIgnore
        }

        return $this->tempDocumentFilename;
    }

    /**
     * @param string $fileName
     * @param string $xml
     */
    protected function savePartWithRels($fileName, $xml): void
    {
        $this->zipClass->addFromString($fileName, $xml);
        if (isset($this->tempDocumentRelations[$fileName])) {
            $relsFileName = $this->getRelationsName($fileName);
            $this->zipClass->addFromString($relsFileName, $this->tempDocumentRelations[$fileName]);
        }
    }

View on GitHub (pinned to aef95c0415)