What goes wrong when a stray dd() or dump() reaches a deployed Laravel app, in a JSON endpoint, a queued job or a Blade view?
answer
- output is written, debug mode or not
- HTML dump ahead of the JSON body
- dd() exits the whole worker
- job reappears after retry_after
- CI check for dd and dump
basics
~20 sDumps are not gated by APP_DEBUG: they still print. In a JSON endpoint they corrupt the body, in a Blade view every visitor sees the data, and dd() in a queued job exits the whole worker, leaving the job to reappear after retry_after.
solid answer
~50 sNothing in Laravel silences `dump()` or `dd()` when `APP_DEBUG=false`, so a forgotten call ships as live behaviour. In a **JSON endpoint** the HTML dump is written ahead of the JSON and the client fails to parse the response; `dd()` replaces the response entirely. In a **Blade view**, `@dump` or `dump()` prints model data to every visitor. In a **queued job**, the worker runs on the CLI dumper, so `dump()` only fills the worker's output, but `dd()` calls exit and ends the whole worker process: the reserved job is neither finished nor failed, so it becomes available again after `retry_after` (90 seconds in the skeleton) and can kill the next worker too, until its attempts run out. Catch dumps before merge with a CI search or an architecture test that forbids `dd` and `dump`, and use `Log::debug()` for anything meant to stay.
code
bash · 5 lines# Fail the build if a dump helper is left in application code
if grep -rnE '(^|[^A-Za-z_>:])(dd|dump)\(|->(dd|dump|ddRawSql|dumpRawSql)\(|@(dd|dump)\b' app routes resources/views; then
echo "Remove dump/dd calls before merging" >&2
exit 1
figo deeper
Know that dump and dd are removed before committing, and that they are not switched off by APP_DEBUG.
Explain what a stray dump does to a JSON response, a Blade page and a command, and why Log::debug is the safe replacement.
Trace the queued-job failure: worker exit, reserved job, retry_after, repeated worker deaths, and set up CI or architecture checks to prevent it.
Define the guardrails that stop debugging code reaching production, from pre-merge checks to how an accidental data exposure is handled.
## Dumps are not debug-mode features `APP_DEBUG` controls how the **exception handler** renders errors. The `dump()` and `dd()` helpers are ordinary functions: Laravel registers a dumper for them in every environment, choosing the HTML dumper for web requests and the CLI dumper for Artisan and workers. Nothing checks `config('app.debug')` before printing. A stray call in production prints exactly as it did on the laptop. ## What breaks, context by context | Where the call sits | `dump()` | `dd()` | |---|---|---| | Controller rendering HTML | dump block above the page for every visitor | page replaced by the dump | | JSON endpoint | HTML dump before the JSON; client parse error | response is only the dump | | Blade view (`@dump`, `@dd`) | data shown inline to every visitor | rendering stops mid-page | | Queued job | CLI dump in the worker's output | **worker process exits** | | Artisan command or scheduled task | dump in command output | command ends early | ## The queued-job case in detail A queue worker is a long-running `php artisan queue:work` process. When a job calls `dd()`: 1. The dump goes to the worker's standard output, typically a process-manager log. 2. `dd()` terminates the PHP process. The job's `handle()` never returns, so the worker neither deletes the job nor marks it failed. 3. The job stays **reserved**. After the connection's `retry_after` (90 seconds for the skeleton's database, Redis and Beanstalkd connections) it becomes available again. 4. The next worker to pick it up hits the same `dd()` and dies as well, until the attempt limit is exceeded and the worker marks the job failed. Meanwhile the process manager keeps restarting workers, and throughput for every other job drops. A `dump()` in a job is milder but still writes model data, possibly personal data, into process logs. ## Why it leaks data, not just breaks pages Dumps show everything reachable from the value: an Eloquent model dump includes its attributes and loaded relations, a request dump includes input and headers. In the grocery app a leftover `dump($customer)` in the checkout view would show every visitor the current customer's address and order history. ## Why reviews miss them 1. A chained `->dump()` reads like any other fluent call, so it slips past a quick skim. 2. Dumps in Blade partials are far from the controller a reviewer is reading. 3. Dumps on error paths or rare branches never fire during manual testing, so nobody sees them before release. ## Catching them before they ship 1. **Review habit:** search the diff for `dd(`, `dump(`, `->dd(`, `->dump(`, `ddRawSql(`, `@dd` and `@dump` before committing. 2. **CI check:** a simple search step over `app/`, `routes/` and `resources/views/` that fails the build on those patterns. 3. **Architecture test:** a test that asserts the `dd` and `dump` functions are not used in application code. 4. **Replace with logs:** anything worth keeping becomes `Log::debug()` with context, which respects `LOG_LEVEL` and never changes a response. ## If one does reach production - Remove it and deploy; there is no config switch that turns dumps off. - For a job dump, check failed jobs and worker restarts, and consider whether the dumped data reached logs that need cleaning. - For a view dump, treat it as a data exposure: identify what was shown and to whom.
- A deployed job with dd() keeps restarting workers. Why does the job not simply fail on the first run?`dd()` ends the PHP process before the worker can catch an exception or record a failure. The job remains reserved, and once `retry_after` passes it is handed out again. Only when a worker picks it up with its attempts already exhausted does the worker mark it failed, so several workers can die first.
- Does setting APP_DEBUG=false in production stop a forgotten dump() from printing?No. `APP_DEBUG` changes how the exception handler renders errors; the dump helpers are registered and print in every environment. The only fix is removing the call, which is why teams add a CI check or architecture test against `dd` and `dump`.
saying these in an interview costs you the question
- APP_DEBUG=false silences dump() and dd() in production.
- dd() in a queued job only stops that job and marks it failed.
- A dump in a JSON endpoint is harmless because clients ignore extra output.
- Blade's @dump only renders for authenticated administrators.
- Debugbar captures dumps so they never reach the page in production.