Intervention/image · error · FileNotWritableException
Failed to write file to path " . $path
Error message
Failed to write file to path " . $path
What it means
File::save() finally writes with file_put_contents($path, $this->toStream()) and throws FileNotWritableException when that call returns false. All pre-checks (directory exists, directory writable, existing file writable) passed, so the failure happened during the write itself: the disk or inode pool is full, a quota was hit, or the filesystem errored (NFS/remote mount issues, fs corruption).
Source
Thrown at src/File.php:108
}
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,
);
}
}
/**
* {@inheritdoc}
*
* @see FileInterface::toString()
*
* @throws StreamException
*/
public function toString(): string
{
$data = stream_get_contents($this->toStream(), offset: 0);
if ($data === false) {
throw new StreamException('Unable to read data from stream');View on GitHub (pinned to 5598b9e397)
Solutions
- Check free space and inodes: df -h and df -i; free space or expand the volume
- Catch FileNotWritableException around save(), surface an actionable error (storage full) instead of a generic failure, and alert ops
- Add disk-space monitoring and a best-effort guard with disk_free_space() before heavy write batches
Example fix
// before
$image->save($path); // throws 'Failed to write file to path ...' when disk is full
// after
try {
$image->save($path);
} catch (FileNotWritableException $e) {
Logger::error('image save failed', ['path' => $path, 'free' => disk_free_space(dirname($path))]);
throw new RuntimeException('Image could not be stored; disk full or quota exceeded', 0, $e);
} Defensive patterns
Strategy: try-catch
Validate before calling
$dir = pathinfo($path, PATHINFO_DIRNAME);
if (disk_free_space($dir) === false || disk_free_space($dir) < $expectedBytes) {
throw new RuntimeException('Insufficient disk space for image write');
}
// best-effort only: the disk can still fill between check and write Try / catch
use Intervention\Image\Exceptions\FileNotWritableException;
try {
$image->save($path);
} catch (FileNotWritableException $e) {
// pre-checks passed, so the write itself failed: disk full, quota, fs error
report('Image write failed: ' . $path . ' free=' . disk_free_space(dirname($path)));
throw $e;
} Prevention
- Monitor free space and inodes (df -h, df -i) on upload volumes
- Alert on FileNotWritableException separately from permission errors
- Prune generated thumbnails/caches so disks cannot grow unbounded
When it happens
Trigger: Writing a large encoded image to a full disk (df shows 100%); hitting an inode limit; exceeding a user/group quota on shared hosting; writing to a failing NFS mount where metadata checks still succeed.
Common situations: Upload/storage volumes filling up in production; log or image caches growing unbounded; shared hosting quotas; long-running jobs whose disk filled after the pre-checks passed.
Related errors
- Can't write to path. Directory "' . $dir . '" does not exist
- Can't write to path. Directory "' . $dir . '" is not writabl
- Can't write to path. Existing file " . $path . " is not writ
- 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/fffe730071ec6b5f.
Report an issue: GitHub.