PHP file_put_contents(): Failed to open stream in Storage and Cache – Permissions Fix Guide
This error usually looks something like: file_put_contents(/var/www/project/storage/logs/laravel.log):
Failed to open stream: Permission denied or file_put_contents(/var/www/project/storage/framework/cache/data/…): Failed to open stream: No such file or directory It basically means PHP tried to write a file and could not. The reasons are almost always:
- The folder does not exist
- PHP is not allowed to write there (permissions / owner)
- The path you gave is wrong
Let’s go through how to fix this properly, both for plain PHP and Laravel.
1. Understand what file_put_contents needs
file_put_contents() is a simple wrapper around opening a file, writing, and closing it.
For this to succeed:
- Every directory in the path must exist
- The directory must be writable by the PHP user
- There must not be any open_basedir or hosting restrictions blocking that path
Example:
file_put_contents('/var/www/project/storage/logs/custom.log', 'Hello');
Directories required:
/var/var/www/var/www/project/var/www/project/storage/var/www/project/storage/logs
The last one, logs, must be writable.
2. Fix for Laravel: storage and cache paths
Laravel writes a lot of files automatically:
- Logs:
storage/logs/laravel.log - Cache:
storage/framework/cache - Sessions:
storage/framework/sessions - Views:
storage/framework/views
If any of these are not writable, you’ll see file_put_contents() errors.
2.1 Make sure folders exist
From your project root:
mkdir -p storage/logs
mkdir -p storage/framework/cache
mkdir -p storage/framework/sessions
mkdir -p storage/framework/views
Laravel normally creates them, but on a manual copy or deploy they can be missing.
2.2 Set correct permissions (Linux)
Typical safe defaults:
chmod -R 775 storage bootstrap/cache
And set the owner to your web server user:
chown -R www-data:www-data storage bootstrap/cache
Replace www-data with apache, nginx, www, or whatever your system uses.
You do not need 777 in almost all cases, and it is not safe on production.
3. Check the error message path carefully
The path in the error is your best clue.
Example:
file_put_contents(/var/www/project/storage/framework/cache/data/33/9f/...):
Failed to open stream: No such file or directory
This tells you:
- PHP is trying to write to
storage/framework/cache/data/... - That subdirectory may not exist
Fix:
mkdir -p storage/framework/cache/data
chmod -R 775 storage/framework/cache
If the message shows something odd like:
file_put_contents(C:\xampp\htdocs\project\storage\app\public\images):
failed to open stream: Is a directory
it means you passed a directory path instead of a full file path. See the next section.
4. Double check the actual path you pass in code
It’s easy to accidentally point to a folder instead of a file, or build a path incorrectly.
Bad:
$path = storage_path('app/public/images'); // directory
file_put_contents($path, $contents); // will fail
Correct:
$path = storage_path('app/public/images/'.time().'.txt'); // file
file_put_contents($path, $contents);
Also make sure you are not mixing leading slashes:
// This drops the base path if you are not careful
$path = base_path().'/'.'/storage/logs/custom.log';
For Laravel, prefer helpers:
$path = storage_path('logs/custom.log');
In plain PHP, build paths like:
$base = __DIR__; // current script directory
$path = $base . '/storage/logs/custom.log';
5. Hosting and open_basedir restrictions
On shared hosting, PHP is often restricted to a specific folder using open_basedir.
If you try to write outside that allowed directory, file_put_contents() will fail even if permissions look fine.
You might see errors like:
open_basedir restriction in effect. File(/tmp/cache.txt) is not within the allowed path(s): (/home/username/:/tmp/)
Fix this by:
- Writing inside an allowed path (like
/home/username/storage/...) - Or changing
open_basedirinphp.ini,.user.ini, or the hosting panel (if allowed)
For Laravel on cPanel, writing inside storage/ and bootstrap/cache under your account home is usually safe.
6. Clearing Laravel cache after fixing permissions
Once you repair permissions and paths, it’s a good idea to clear cache so Laravel can rebuild things cleanly.
From project root:
php artisan config:clear
php artisan cache:clear
php artisan view:clear
php artisan route:clear
php artisan optimize:clear
If these commands previously failed with file_put_contents errors, they should now work.
7. Example: custom logging in Laravel with safe storage path
If you want to write a simple log file yourself:
$path = storage_path('logs/custom-info.log');
if (! file_exists(dirname($path))) {
mkdir(dirname($path), 0755, true);
}
file_put_contents($path, '['.now().'] Hello from custom log'.PHP_EOL, FILE_APPEND);
This ensures the parent directory exists and appends safely.
8. Quick checklist
When you see file_put_contents(): Failed to open stream in storage or cache:
- Read the full error and note the exact path
- Confirm that every directory in the path exists
- For Laravel, make sure
storage/andbootstrap/cacheexist and are writable - Set permissions:
chmod -R 775 storage bootstrap/cache(and chown to the web user) - Ensure you are writing to a file, not a directory
- Check for open_basedir restrictions or weird absolute paths
- Clear Laravel caches after fixing permissions
Once paths and permissions are correct, file_put_contents() will quietly do its job and your logs, cache, and uploaded files will be written without errors.