Intervention/image · error · DirectoryNotFoundException

Can't write to path. Directory "' . $dir . '" does not exist

Error message

Can't write to path. Directory "' . $dir . '" does not exist

What it means

Before writing, File::save() extracts the target directory with pathinfo($path, PATHINFO_DIRNAME) and verifies it exists with is_dir(). A missing directory throws DirectoryNotFoundException (a FilesystemException) - the library never creates directories for you.

Source

Thrown at src/File.php:87

     * @throws FileNotWritableException
     * @throws StreamException
     */
    public function save(string $path): void
    {
        if ($path === '') {
            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());

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Create the directory beforehand: if (!is_dir($dir)) { mkdir($dir, 0775, true); }
  2. Use absolute paths (e.g. base_path()/public_path() helpers) so the cwd cannot change resolution
  3. Ensure the storage directory ships with your deployment or is created in a bootstrap step

Example fix

// before
$image->save('uploads/' . date('Y/m') . '/photo.jpg'); // dir may not exist

// after
$dir = 'uploads/' . date('Y/m');
if (!is_dir($dir)) {
    mkdir($dir, 0775, true);
}
$image->save($dir . '/photo.jpg');
Defensive patterns

Strategy: validation

Validate before calling

$dir = pathinfo($path, PATHINFO_DIRNAME);
if (!is_dir($dir)) {
    mkdir($dir, 0775, true);
}
$encoded->save($path);

Try / catch

use Intervention\Image\Exceptions\DirectoryNotFoundException;

try {
    $image->save($path);
} catch (DirectoryNotFoundException $e) {
    mkdir(pathinfo($path, PATHINFO_DIRNAME), 0775, true);
    $image->save($path);
}

Prevention

When it happens

Trigger: Calling $image->save('uploads/2026/08/photo.jpg') when 'uploads/2026/08' was never created; passing a relative path that resolves against an unexpected working directory (queue worker cwd vs web cwd) so is_dir() looks in the wrong place.

Common situations: Date-partitioned upload folders that only exist after the first write of that period; deploying without the storage directory; Docker/containers where the volume is mounted elsewhere; relative paths in artisan queue jobs.

Related errors


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