Intervention/image · error · FileNotWritableException
Can't write to path. Directory "' . $dir . '" is not writabl
Error message
Can't write to path. Directory "' . $dir . '" is not writable
What it means
After confirming the directory exists, File::save() checks is_writable($dir) and throws FileNotWritableException when the PHP process lacks write permission on that directory. This is a classic ownership mismatch: the directory belongs to a different user than the one PHP runs as (www-data, php-fpm user, queue worker user).
Source
Thrown at src/File.php:93
throw new InvalidArgumentException('Path must not be an empty string');
}
if (strlen($path) > PHP_MAXPATHLEN) {
throw new InvalidArgumentException(
"Path is longer than the configured max. value of " . PHP_MAXPATHLEN,
);
}
$dir = pathinfo($path, PATHINFO_DIRNAME);
if (!is_dir($dir)) {
throw new DirectoryNotFoundException(
'Can\'t write to path. Directory "' . $dir . '" does not exist',
);
}
if (!is_writable($dir)) {
throw new FileNotWritableException(
'Can\'t write to path. Directory "' . $dir . '" is not writable',
);
}
if (is_file($path) && !is_writable($path)) {
throw new FileNotWritableException(
"Can't write to path. Existing file " . $path . " is not writable",
);
}
// write data
$saved = file_put_contents($path, $this->toStream());
if ($saved === false) {
throw new FileNotWritableException(
"Failed to write file to path " . $path,
);
}View on GitHub (pinned to 5598b9e397)
Solutions
- Give the PHP user write access: chown the directory to the web server user or a shared group, and use chmod 775
- Use ACLs for multi-user setups: setfacl -m u:www-data:rwx storage/uploads
- Verify the mount is writable and not read-only (check docker-compose volumes, /etc/fstab, SELinux context)
Example fix
# before: dir owned by deploy user, mode 755 -> www-data cannot write # after: sudo chgrp www-data storage/uploads sudo chmod 775 storage/uploads # or per-user ACL without changing group: sudo setfacl -m u:www-data:rwx storage/uploads
Defensive patterns
Strategy: validation
Validate before calling
$dir = pathinfo($path, PATHINFO_DIRNAME);
if (!is_writable($dir)) {
throw new RuntimeException('Storage directory not writable by PHP user: ' . $dir);
}
$encoded->save($path); Try / catch
use Intervention\Image\Exceptions\FilesystemException;
try {
$image->save($path);
} catch (FilesystemException $e) {
// check ownership/modes before retrying; do not blind-retry
throw new RuntimeException('Cannot save image: ' . $e->getMessage(), 0, $e);
} Prevention
- chown/chgrp storage directories to the PHP-FPM user with mode 775
- Use setfacl when multiple users write to the same tree
- Verify container mounts are read-write and check SELinux contexts on RHEL-type hosts
When it happens
Trigger: Saving to a directory owned by the deploy user with mode 755 while PHP-FPM runs as www-data; writing into a read-only container mount; SELinux or AppArmor denying writes despite permissive Unix modes; shared hosting where the storage dir belongs to another FTP account.
Common situations: Files uploaded/deployed as root and never chowned; Laravel-style storage dirs created by CLI then written by the web user; NFS mounts with root_squash; containers with read-only volumes.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Can't write to path. Existing file " . $path . " is not writ
- Can't write to path. Directory "' . $dir . '" does not exist
- Failed to write file to path " . $path
- Failed to open file from path "' . $path . '"
- Path must not be an empty string
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/87a780ca2c4357db.
Report an issue: GitHub.