Era Host hosting
EraHost – Free Domain, Cheap Hosting!
Client Area
Support 24/7
Menu

Fixing ZipArchive::close(): Can't Open File — Permission Denied in PHP

3 min read
07.02.2026

1. Error Meaning & Causes

PHP cannot create/modify ZIP files because:

ZipArchive Permission Denied
ZipArchive::close fails — target dir not writable; check temp + output both.

For related PHP zip / archive topics, see Fix ZIP Extension Needs to Be Loaded, session_start() failed: Permission denied (13), and "No Space Left on Device (28)".

  • Insufficient file/folder permissions
  • Wrong ownership (Apache/Nginx has no access)
  • SELinux/AppArmor restrictions
  • Disk space or inode limits
  • Temporary directory misconfiguration
Linux VDS
High performance for your projects
  • Root access and flexible setup
  • Control panel
  • NVMe disks
  • DDR5
Linux VDS

2. Check and Fix File/Folder Permissions

Find target directory in your code:
$zip = new ZipArchive();
$filename = "/var/www/html/uploads/archive.zip";
Set correct permissions & ownership:
sudo chmod -R 775 /var/www/html/uploads/
sudo chown -R www-data:www-data /var/www/html/uploads/  # Apache
sudo chown -R nginx:nginx /var/www/html/uploads/        # Nginx

3. PHP Configuration (php.ini)

Check and modify php.ini:
php --ini | grep "Loaded Configuration File"
sudo nano /etc/php/8.0/apache2/php.ini

Check these settings:

  • disable_functions - Ensure exec/system not disabled
  • open_basedir - Ensure ZIP directory is in allowed paths
Restart services:
sudo systemctl restart apache2
sudo systemctl restart nginx php8.0-fpm

4. SELinux/AppArmor Restrictions

Check & fix security modules:
# SELinux
sestatus
sudo chcon -R -t httpd_sys_rw_content_t /var/www/html/uploads/

# AppArmor (Ubuntu/Debian)
sudo aa-status
sudo aa-complain /usr/sbin/php-fpm

5. Disk Space and Inodes

Check space & clear files:
df -h /var
df -i /var
sudo rm -rf /tmp/*

6. Temporary Directory Setup

Set temp directory in php.ini:
sys_temp_dir = "/var/www/html/uploads/tmp"
upload_tmp_dir = "/var/www/html/uploads/tmp"

# Create and set permissions
mkdir -p /var/www/html/uploads/tmp
sudo chmod -R 777 /var/www/html/uploads/tmp

7. Debugging with Error Reporting

Enable debugging in your script:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

$zip = new ZipArchive();
$file = "/var/www/html/uploads/test.zip";

if ($zip->open($file, ZipArchive::CREATE) !== TRUE) {
    die("Error: Unable to create ZIP file. Check permissions.");
}
$zip->addFromString("test.txt", "Hello World!");
$zip->close();
?>

8. Summary of Fixes

IssueFixCommand
Folder permissionsSet 775chmod -R 775 /var/www/html/uploads/
Wrong ownershipChange ownerchown -R www-data:www-data /var/www/html/uploads/
SELinux blockSet contextchcon -R -t httpd_sys_rw_content_t /var/www/html/uploads/
Full disk/inodesClear spacedf -h; df -i; rm -rf /tmp/*
Temp dir issuesSet in php.inisys_temp_dir = "/path/to/tmp"
PHP restrictionsModify php.iniCheck disable_functions & open_basedir
Quick Fix Sequence:
  1. Check target directory permissions
  2. Verify ownership matches web server user
  3. Check SELinux/AppArmor status
  4. Ensure sufficient disk space
  5. Test with debugging enabled

Follow these fixes to resolve ZipArchive permission errors in PHP.

Frequently asked questions
PHP's `sys_get_temp_dir()` — usually /tmp. ZipArchive creates a tempfile there for partial builds, then atomically rename to your output path. If /tmp is read-only or out of space, ZipArchive can't open temp file → perm denied at close. Verify /tmp is writable + has 2x the expected output size free.
`open_basedir` in php.ini limits paths PHP can read/write. If your ZipArchive output path is outside open_basedir's allowed roots, permission denied. Either: extend open_basedir to include the output path, or write to a path that's already inside (typical: under document root or ~/tmp).
Different user. Cron runs as root or per-user; web PHP runs as www-data/nginx/apache. Cron creates the file owned by root, perms 644 — web PHP can't overwrite later. Standard fix: PHP-FPM pool runs as same user that owns the upload dir, or chmod 775 + chown to the right group.
ZipArchive needs RAM proportional to file count (not total size) — index structure for 1M files chews ~200MB RAM. PHP `memory_limit` exhaustion manifests as zip close failure (since the temp file partially written, then PHP died). Raise `memory_limit` to 512M+ for archives with > 100k entries. Or split into chunked archives.
Related articles
Fixing session_start() failed: Permission denied (13) — A System Administrator's Guide
Fixing PHP session_start(): Permission Denied (13) Error
Fixing session_start(): Permission Denied (13) — Failed to Read Session Data in PHP