Fixing ZipArchive::close(): Can't Open File — Permission Denied in PHP
07.02.2026
1. Error Meaning & Causes
PHP cannot create/modify ZIP files because:
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
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 disabledopen_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
| Issue | Fix | Command |
|---|---|---|
| Folder permissions | Set 775 | chmod -R 775 /var/www/html/uploads/ |
| Wrong ownership | Change owner | chown -R www-data:www-data /var/www/html/uploads/ |
| SELinux block | Set context | chcon -R -t httpd_sys_rw_content_t /var/www/html/uploads/ |
| Full disk/inodes | Clear space | df -h; df -i; rm -rf /tmp/* |
| Temp dir issues | Set in php.ini | sys_temp_dir = "/path/to/tmp" |
| PHP restrictions | Modify php.ini | Check disable_functions & open_basedir |
Quick Fix Sequence:
- Check target directory permissions
- Verify ownership matches web server user
- Check SELinux/AppArmor status
- Ensure sufficient disk space
- Test with debugging enabled
Follow these fixes to resolve ZipArchive permission errors in PHP.
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.
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


