
Debug mode is controlled by APP_DEBUG in the .env file: true locally, false in production, always. Check the real state with php artisan about --only=environment. If the change has no effect, the configuration is cached: run php artisan config:clear.
Debug mode decides what a visitor sees when your application crashes: the full stack trace with source code and environment variables, or a neutral error page. It is a one-line setting, and also one of the most common data leaks in production.
Part of the Web development reading path. Checked on Laravel 13.30.1 with PHP 8.4.25.
Turning it on and off
The setting lives in the .env file at the root of the project, and nowhere else:
APP_ENV=local
APP_DEBUG=trueTo turn it off, set the value to false:
APP_ENV=production
APP_DEBUG=falseCheck the effective state without writing a single line of code:
php artisan about --only=environment Environment ........................................................ local
Debug Mode ...................................................... ENABLEDThat is the only check that counts: it shows the value the application really uses, cache included.
The trap: cached configuration
You set APP_DEBUG=false, you reload, and the stack traces are still there. It is almost always the configuration cache.
Once php artisan config:cache has run, Laravel writes every resolved value into bootstrap/cache/config.php and stops reading the .env file altogether. The behaviour was measured:
| Step | config('app.debug') | env('APP_DEBUG') |
|---|---|---|
APP_DEBUG=true, no cache | true | true |
after config:cache, then switched to false in .env | true | NULL |
after config:clear | false | false |
Two lessons. The first: after any change to .env on a server where the configuration is cached, you have to rebuild it.
php artisan config:clear
# or, in production, rebuild the cache straight away
php artisan config:cacheThis is the least understood consequence, and it goes well beyond debugging. A call to env('MA_CLE') anywhere outside a config/ file returns null as soon as config:cache has run. The rule is strict: env() inside config/ only, and config('fichier.cle') everywhere else.
What config/app.php contains
The configuration key does nothing more than read the environment variable, with false as the fallback:
'debug' => (bool) env('APP_DEBUG', false),Leave that line alone. It is written so the default behaviour is the safe one: if APP_DEBUG is missing from .env, debug mode stays off. Checked by removing the variable, config('app.debug') does return false.
Hard-coding the value in config/app.php has two drawbacks: the file is under version control, so the setting ships to every environment, and the .env file becomes misleading.
The accepted values follow Laravel’s conversion rules, measured line by line:
In .env | config('app.debug') |
|---|---|
APP_DEBUG=true or (true) or 1 | true |
APP_DEBUG=false or 0 | false |
APP_DEBUG=yes | true |
| variable missing | false |
yes evaluates to true because the string is not recognised as a boolean and ends up being cast. That is a good reason to stick to true and false.
Why false in production is not negotiable
With APP_DEBUG=true, the error page shows the call stack, snippets of source code and the contents of the loaded environment variables. A visitor who triggers an error can therefore read your database credentials, your API keys and the APP_KEY that encrypts your sessions.
No hunting is needed: one URL that throws an exception is enough. That is how Laravel applications end up compromised without any particular flaw in the application itself.
The right configuration for a production server, like the one built in installing Laravel on Debian, fits in three lines:
APP_ENV=production
APP_DEBUG=false
APP_URL=https://exemple.comThen, once deployed:
php artisan config:cache
php artisan about --only=environment # check: Debug Mode must show OFFThe same reasoning applies to public forms, which need protecting against automated submissions before you open them to the world.
Errors are still there to read, but in the logs rather than in the browser:
tail -f storage/logs/laravel.logThat path is built with storage_path(), covered in the application paths.
Common errors
config:cache, Laravel no longer reads the .env file. Any change calls for config:clear or a cache rebuild.env() returns NULL everywhere else. Use config('fichier.cle').

