Reader Stacks

Enabling and Disabling Debug Mode in Laravel

APP_DEBUG in .env, why it must always be false in production, and what actually leaks when it is left on by mistake.

Debug mode controls whether Laravel shows a detailed error page (full stack trace, the exact query that failed, environment variable values in some cases) or a generic error page when something goes wrong.

Where it's set

# .env
APP_DEBUG=true   # local development
APP_DEBUG=false  # production, always

This is read by config/app.php's debug key, which defaults to env('APP_DEBUG', false) — so if the environment variable is ever missing entirely, Laravel falls back to false (safe by default), not true.

Why leaving it on in production is a real security issue

With debug mode on, an unhandled exception shows a full stack trace to anyone who triggers it — including file paths, the exact SQL query and bindings involved, and sometimes configuration values interpolated into error messages. This is genuinely useful information for an attacker probing for weaknesses, not just an ugly page.

Config caching interaction

If the app runs php artisan config:cache in production (recommended for performance), the cached config is what's actually used — changing APP_DEBUG in .env after caching has no effect until you run php artisan config:cache again. This is a common reason people think they've turned debug mode off and it's still showing detailed errors.

Checking the current value at runtime

if (config('app.debug')) {
    // debug mode is on
}

A safer pattern for staging environments

If a staging environment needs more detail than production but shouldn't be fully public, prefer a proper logging/error-tracking setup (Sentry, Flare, or just detailed log-level configuration) over enabling APP_DEBUG — that gives developers the detail they need without exposing it to every visitor who happens to trigger an error.

Debug mode and log level are separate controls

Turning APP_DEBUG off does not mean Laravel stops recording useful errors. Production should normally keep detailed exception information in server-side logs or an error tracker while returning a generic response to the browser. The public error page and the private diagnostic record solve different problems; do not turn debug mode back on just because you need more detail in a production incident.

Do not call env() throughout application code

Laravel's configuration cache changes how environment variables are loaded. Application code should read config('app.debug'), as shown above, rather than calling env('APP_DEBUG') in controllers or services. Environment access belongs in configuration files; runtime code then reads the resolved configuration value consistently whether config caching is enabled or not.

Verify the deployed value from the application, not only from the .env file

If a production host has multiple releases, containers, or process managers, editing one .env file does not prove the running PHP process is using it. After changing configuration, rebuild the config cache as part of the deployment and verify the effective value from the deployed application or a one-off Artisan command. This avoids the particularly dangerous case where the file says false while the cached configuration still says true.

What to do if debug mode was exposed publicly

First disable it and refresh the cached configuration. Then treat any secrets that were actually exposed in an exception page or screenshot as compromised: rotate those credentials rather than assuming nobody saw them. The risk is not that every debug page automatically prints every secret; it is that detailed request, query, path, and exception context can reveal information that was never intended for an unauthenticated visitor.

Topics: Deployment & Hosting Debugging & Testing