{"record":{"id":"2a8c2824329e59c8","repo":"Intervention/image","slug":"can-t-write-to-path-existing-file-path-i","errorCode":null,"errorMessage":"Can't write to path. Existing file \" . $path . \" is not writable","messagePattern":"Can't write to path\\. Existing file \" \\. \\$path \\. \" is not writable","errorType":"exception","errorClass":"FileNotWritableException","httpStatus":null,"severity":"error","filePath":"src/File.php","lineNumber":99,"sourceCode":"            );\n        }\n\n        $dir = pathinfo($path, PATHINFO_DIRNAME);\n\n        if (!is_dir($dir)) {\n            throw new DirectoryNotFoundException(\n                'Can\\'t write to path. Directory \"' . $dir . '\" does not exist',\n            );\n        }\n\n        if (!is_writable($dir)) {\n            throw new FileNotWritableException(\n                'Can\\'t write to path. Directory \"' . $dir . '\" is not writable',\n            );\n        }\n\n        if (is_file($path) && !is_writable($path)) {\n            throw new FileNotWritableException(\n                \"Can't write to path. Existing file \" . $path . \" is not writable\",\n            );\n        }\n\n        // write data\n        $saved = file_put_contents($path, $this->toStream());\n\n        if ($saved === false) {\n            throw new FileNotWritableException(\n                \"Failed to write file to path \" . $path,\n            );\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @see FileInterface::toString()","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/File.php#L81-L117","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","solutions":["Fix ownership/permissions of the existing file: chown/chgrp to the writing user, chmod 664","Unset the immutable attribute if set: chattr -i file (as root)","If overwrite protection is intentional, write to a new file (versioned or hashed name) instead","Delete the stale file before saving when regeneration is acceptable"],"exampleFix":"# before: cached thumb owned by root, mode 644 -> web user cannot overwrite\n# after:\nsudo find storage/thumbs -type f -exec chgrp www-data {} +\nsudo find storage/thumbs -type f -exec chmod 664 {} +","handlingStrategy":"validation","validationCode":"if (is_file($path) && !is_writable($path)) {\n    unlink($path); // or fix permissions first\n}\n$encoded->save($path);","typeGuard":null,"tryCatchPattern":"use Intervention\\Image\\Exceptions\\FileNotWritableException;\n\ntry {\n    $image->save($path);\n} catch (FileNotWritableException $e) {\n    if (is_file($path) && !is_writable($path)) {\n        // regenerate under a versioned name instead of overwriting\n        $image->save($path . '.' . time());\n    }\n}","preventionTips":["Generate files as the same system user that later overwrites them","Avoid chmod 444 on files that must be regenerated","Write versioned/hashed filenames when overwrite is not required"],"tags":["php","intervention-image","file","save","permissions","filesystem"],"backgroundTag":"permission-denied","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}