Laravel "The stream or file ... log ... could not be opened" in CI
By Kaveh Alemi·Latchkey
Monolog could not open the daily or single log file under storage/logs. The directory is missing or not writable by the CI user. Create and chmod it, or switch the log channel to stderr so CI captures logs without touching disk.
What this error means
A request or command fails with "The stream or file \"storage/logs/laravel.log\" could not be opened in append mode: Failed to open stream: Permission denied" or "No such file or directory".
php
UnexpectedValueException: The stream or file
"/home/runner/work/app/storage/logs/laravel.log" could not be opened
in append mode: Failed to open stream: Permission denied
Diagnose it: version, extensions, and limits
Terminal
php -v
php -m
php -i | grep -E "memory_limit|max_execution_time|error_reporting"
# a runner default is often far tighter than your local php.ini
php -d memory_limit=-1 vendor/bin/<tool>
Common causes
storage/logs is missing or unwritable
The logs directory was not created after checkout, or its permissions do not allow the runner user to write, so Monolog fails to open the file.
The default file log channel is used in CI
Writing to a file adds a filesystem dependency that a stateless CI job often does not need and that breaks on permission issues.
How to fix it
Create and make the logs directory writable
Create storage/logs if missing.
chmod it writable for the runner user.
Re-run so Monolog can append to the file.
Terminal
mkdir -p storage/logs
chmod -R 777 storage/logs
Log to stderr in CI
Set LOG_CHANNEL=stderr so logs go to the job output and no file needs to be writable.
.github/workflows/ci.yml
env:LOG_CHANNEL:stderr
How to prevent it
Keep storage/logs present and writable in CI.
Prefer LOG_CHANNEL=stderr for stateless runners.
Match runner user ownership to the checked-out tree.
Frequently asked questions
What causes Laravel "The stream or file ... log ... could not be opened" in CI?
There are 2 common causes: storage/logs is missing or unwritable and the default file log channel is used in ci. The logs directory was not created after checkout, or its permissions do not allow the runner user to write, so Monolog fails to open the file.
How do I fix Laravel "The stream or file ... log ... could not be opened" in CI?
There are 2 fixes depending on which cause you have: create and make the logs directory writable and log to stderr in ci. Work through them in order, since the first is the most common.
What does Laravel "The stream or file ... log ... could not be opened" in CI actually mean?
A request or command fails with "The stream or file \"storage/logs/laravel.log\" could not be opened in append mode: Failed to open stream: Permission denied" or "No such file or directory".
How do I stop Laravel "The stream or file ... log ... could not be opened" in CI happening again?
Keep storage/logs present and writable in CI. The prevention section lists 3 changes that keep it from recurring.