Intervention/image · error · FileNotWritableException

Can't write to path. Existing file " . $path . " is not writ

Error message

Can't write to path. Existing file " . $path . " is not writable

What it means

File::save() additionally checks an existing target file: if is_file($path) is true but is_writable($path) is false, it throws FileNotWritableException. The directory is fine; the file being overwritten was created by another user or was made read-only (mode 644 owned by someone else, 444, or the immutable attribute).

Source

Thrown at src/File.php:99

            );
        }

        $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,
            );
        }
    }

    /**
     * {@inheritdoc}
     *
     * @see FileInterface::toString()

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Fix ownership/permissions of the existing file: chown/chgrp to the writing user, chmod 664
  2. Unset the immutable attribute if set: chattr -i file (as root)
  3. If overwrite protection is intentional, write to a new file (versioned or hashed name) instead
  4. Delete the stale file before saving when regeneration is acceptable

Example fix

# before: cached thumb owned by root, mode 644 -> web user cannot overwrite
# after:
sudo find storage/thumbs -type f -exec chgrp www-data {} +
sudo find storage/thumbs -type f -exec chmod 664 {} +
Defensive patterns

Strategy: validation

Validate before calling

if (is_file($path) && !is_writable($path)) {
    unlink($path); // or fix permissions first
}
$encoded->save($path);

Try / catch

use Intervention\Image\Exceptions\FileNotWritableException;

try {
    $image->save($path);
} catch (FileNotWritableException $e) {
    if (is_file($path) && !is_writable($path)) {
        // regenerate under a versioned name instead of overwriting
        $image->save($path . '.' . time());
    }
}

Prevention

When it happens

Trigger: Overwriting a file created by a root CLI command or by another service user; replacing cached images generated by a different process; files deliberately set to 444 to prevent modification; files with the immutable flag (chattr +i).

Common situations: Mixed CLI/web processing where artisan-generated thumbnails are later overwritten by the web worker; deploy pipelines leaving root-owned assets; CDN-style caches made read-only to guard against accidental edits.

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


AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23). Data as JSON: /api/errors/2a8c2824329e59c8. Report an issue: GitHub.