Deployment & server errors
Fix 500s, broken uploads, dead queues and failed cron after a deploy — caches, migrations, storage links, the cron.php entry point and safe rollback.
Deployment & server errors
Something broke after a deploy, an update or a server change: white screens, 500s, uploads that 404, a queue that stopped draining, or cron that silently is not running. On shared hosting (cPanel/Apache) most of these come down to five things: caches built for the wrong environment, migrations not run, the storage symlink missing, the cron entry point not wired, or a .env that did not travel. Work down this page; each step is a check you can actually perform.
Who this is for: the super admin performing the deploy or update, and developers supporting one.
Problem
The app is up but unhealthy, or unhealthy after a change you just made — and you need to get back to a known-good state without guessing.
What you see
| Symptom | First suspect |
|---|---|
| White page / HTTP 500 for all pages | Environment or caches built elsewhere, missing APP_KEY, permission errors |
SQLSTATE errors |
Migrations not run, or wrong database credentials |
| Uploads and images broken (404) | Missing storage symlink |
Queue never processes; sync driver in production |
Worker not running / driver misconfigured |
| Scheduled jobs never fire | Cron entry missing or cron.php unreachable |
| Errors only after an update | Cache staleness or a failed migration — rollback path below |
| "Please provide a valid cache path" / view errors | storage/framework/ directories missing or not writable |
Likely causes
- Deployed files without running the migration step, or without clearing/rebuilding caches — a cached config from the old release is the classic post-deploy 500.
storage/andbootstrap/cache/not writable by the web user on the new host.- No
storage:linkafter a fresh deployment or move. - The single
cron.phpentry point (shared hosting) or theschedule:runcron line (VPS) missing — everything "scheduled" then quietly stops. - Queue worker not running, or running without the full queue list.
.envmissing or still holding development values (APP_DEBUG=true, wrongAPP_URL,LOG_LEVELtoo noisy to find anything).
Quick fix
The one-click recovery pass — on Super Admin → Settings → System Health (/super-admin/settings/system-health), in this order:
- Clear caches (
optimize:clear) — the first thing to try after any deploy. - Run migrations (
migrate --force) — if the update brought schema changes,php artisan migrate:statusshould then be clean. - Rebuild caches — only once the app is confirmed working; rebuilding too early bakes in a broken state.
- Storage link (
storage:link) — restores public access to uploads. - Restart queue (
queue:restart) — graceful worker restart; note the page warns when the driver issync, in which case this action does not help and the driver itself needs fixing.
Step-by-step fix
- Confirm the blast radius.
GET /api/v1/health— 503 tells you which core check (db,cache,storage) is failing. One workspace broken usually means data; everything broken means infrastructure. - Read the log.
storage/logs/laravel.log(stack → single driver). IfLOG_LEVELis high, the newest entries are still there — read from the end. Fix the exception class you see, not the symptom you first heard about. - Environment check.
.envexists, is readable, and holds the right values:APP_KEY(missing key = instant crypto failures),APP_URL(drives generated URLs, webhooks and redirects — a wrong value silently breaks webhook callbacks), database credentials,QUEUE_CONNECTION. Reference: Environment. - Permissions.
storage/andbootstrap/cache/must be writable by the web server user, recursively. On cPanel, that is usually 775 with the right group — and recheck it after every deploy, because uploading files often resets ownership. - Storage link.
php artisan storage:link(or the System Health action). Verify by opening a known uploaded file's URL. - Maintenance mode around risky steps.
php artisan downbefore a manual fix,php artisan upafter verifying — and remember the last step of any incident is turning it back up. - Cron on shared hosting. One entry runs everything:
cron.phpevery minute. It drains the queue within a time budget (max 30 jobs, ~55 seconds) and then runs the scheduler. If web-reachable cron is used,CRON_SECRETprotects the endpoint. Check the hosting panel that the cron is actually still configured — after a hosting migration it is the most commonly forgotten piece. - Workers.
php artisan queue:work --queue=default,webhooks,automations,integrations,notifications,exports,ai-sdr,mail. All queues on one list. Supervise or restart it after every deploy so it picks up new code. - Applying an update properly. Use Super Admin → Settings → Updates (
/super-admin/settings/updates): applying creates a pre-update backup automatically — note its name before clicking, because rollback is "restore that backup" from the Backups page. After the update: clear caches, run migrations, restart the queue, then health-check. - Rollback when it goes wrong. Super Admin → Settings → Backups (
/super-admin/settings/backups): verify the pre-update backup, then use Restore (extracts the zip, imports the SQL, reports files restored and rows imported). Deployments on a VPS can roll back code with your normal tooling, but the database side is the backup restore — plan for both.
Admin fix
- The one-click pass above (System Health + Updates + Backups) covers the whole admin-side toolkit.
- Keep a short written runbook for your own hosting: where the cron is configured, where the worker is supervised, how the site is deployed. The next deploy, done under pressure, will follow it.
Developer fix
- Common root: caches (config/route/view) built under one environment served under another.
optimize:clearthen rebuild after switch/move. cron.phpbootstraps the kernel explicitly for shared hosting, enforces the 30-job/55-second budget, checksCRON_SECRETfor web access, then runs the queue drain andschedule:run.- Vue/asset build outputs and
public/buildmust be deployed alongside PHP; a JS error breaking the panel usually looks like "server is broken" in a screenshot but has no server exception. - Check
APP_DEBUGbefore anything else when a screenshot shows a stack trace to an end user — debug mode must be off in production.
Logs to check
storage/logs/laravel.log— the primary source; read the newest entries first.- Hosting panel: cron history/error mail, PHP error log, disk quota.
php artisan migrate:status— any pending migration after a deploy is a red flag.GET /api/v1/health— the fast external verdict after every step.
When to escalate
- Restores fail or the backup turns out unverifiable — stop, preserve everything, escalate to the platform owner before touching production further.
- The database itself is unreachable or the host is out of disk/quota — hosting support is the only fix.
- A reproducible 500 that survives cache clearing, migrations and an untouched
.env— capture the full stack trace (with debug on, temporarily, on a staging copy) and hand it to the developer.
Related guides
Was this page helpful?
Thanks — noted. ✦