TL;DR
Laravel 12 introduces several breaking changes that surface as cryptic errors during or after upgrade. The most common issues include: the shift from Laravel Mix to Vite being enforced (Mix support fully removed), changes to the default exception handler, updated minimum PHP version requirements (PHP 8.2+), removal of deprecated Eloquent methods, and third-party package incompatibilities where packages pinned to laravel/framework ^11.0 refuse to install. This guide walks you through identifying the symptoms, understanding the root cause, and implementing a production-tested fix with real code examples.
Symptoms
If you’re experiencing this issue, you’ll likely notice one or more of these signs in your application:
- composer update fails with dependency resolution errors
- Class not found errors for removed facade aliases
- Method not found errors on Eloquent models for removed deprecated methods
- Test suite failures due to updated assertion signatures
- Vite build errors when Mix webpack config still exists
- Package X requires laravel/framework ^11.0 but ^12.0 is installed
If any of these symptoms look familiar, you’re dealing with laravel 12 upgrade gotchas and package incompatibilities. Read on to understand why it happens and how to fix it properly.
Root Cause
Laravel 12 introduces several breaking changes that surface as cryptic errors during or after upgrade. The most common issues include: the shift from Laravel Mix to Vite being enforced (Mix support fully removed), changes to the default exception handler, updated minimum PHP version requirements (PHP 8.2+), removal of deprecated Eloquent methods, and third-party package incompatibilities where packages pinned to laravel/framework ^11.0 refuse to install. The upgrade guide covers the framework changes, but ecosystem package compatibility is the biggest time sink.
Understanding the root cause is critical before applying a fix — treating only the symptoms often leads to the problem resurfacing in a different form, especially under production load.
How to Fix
Follow these steps in order. Each step builds on the previous one, and skipping steps may result in an incomplete fix.
Step 1: Read the official Laravel 12 upgrade guide completely before starting
Read the official Laravel 12 upgrade guide completely before starting
Step 2: Update PHP to 8.2+
Update PHP to 8.2+ — check with php -v and update your Docker/server config
Step 3: Run composer update --dry-run first to identify all dependency conflicts without changing anything
Run composer update --dry-run first to identify all dependency conflicts without changing anything
Step 4: Update third-party packages one at a time: check each package’s GitHub for Laravel 12 support branches
Update third-party packages one at a time: check each package’s GitHub for Laravel 12 support branches
Step 5: For packages without Laravel 12 support yet, check for community forks or use composer’s —ignore-platform-req temporarily
For packages without Laravel 12 support yet, check for community forks or use composer’s —ignore-platform-req temporarily
Step 6: Remove any remaining Laravel Mix config files (webpack.mix.js) and ensure Vite is configured
Remove any remaining Laravel Mix config files (webpack.mix.js) and ensure Vite is configured
Step 7: Update deprecated Eloquent calls: replace $model->forceDelete() patterns, Model::unguard() usage, and removed scope methods
Update deprecated Eloquent calls: replace $model->forceDelete() patterns, Model::unguard() usage, and removed scope methods
Step 8: Run your full test suite after upgrade, fixing deprecation warnings as you go
Run your full test suite after upgrade, fixing deprecation warnings as you go
Step 9: Clear all caches: php artisan config:clear && php artisan cache:clear && php artisan route:clear && php artisan view:clear
Clear all caches: php artisan config:clear && php artisan cache:clear && php artisan route:clear && php artisan view:clear
Code Example
The following before/after comparison shows the core pattern you need to change. Pay attention to the comments explaining why each change matters.
Before (Broken)
// composer.json — before upgrade
{
"require": {
"php": "^8.1",
"laravel/framework": "^11.0",
"spatie/laravel-permission": "^5.0",
"laravel/sanctum": "^3.0"
}
}
// app/Exceptions/Handler.php — old exception handler
class Handler extends ExceptionHandler
{
protected $dontReport = [...];
protected $dontFlash = [...];
}
After (Fixed)
// composer.json — after upgrade
{
"require": {
"php": "^8.2",
"laravel/framework": "^12.0",
"spatie/laravel-permission": "^6.0",
"laravel/sanctum": "^4.0"
}
}
// bootstrap/app.php — Laravel 12 exception handling
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
return Application::configure(basePath: dirname(__DIR__))
->withExceptions(function (Exceptions $exceptions) {
$exceptions->dontReport([
// your exception classes
]);
})->create();
Key Takeaways
- Identify before you fix: Use the symptoms checklist above to confirm you’re dealing with this specific issue, not a different problem with similar error messages
- Test under load: Many of these issues only surface under concurrent access — always verify your fix with load testing before deploying to production
- Monitor after deployment: Set up alerting for the symptoms listed above so you catch regressions early
Difficulty Level
Intermediate
This guide assumes familiarity with the framework and its core tooling. You should understand basic database concepts, configuration patterns, and be comfortable reading framework source code when needed. Prior experience with similar issues will help but is not required.
Frequently Asked Questions
How long does a Laravel 12 upgrade typically take?
For a well-tested application with 80%+ test coverage, expect 2-4 hours for the framework upgrade itself and 1-2 days for resolving third-party package incompatibilities. Applications with no tests or heavy reliance on deprecated features may take a full week. Always upgrade on a branch and run your test suite before deploying.
Can I skip from Laravel 10 directly to Laravel 12?
Technically possible but not recommended. Each major version removes deprecations from the previous version. Jumping two versions means dealing with both sets of breaking changes simultaneously. Upgrade 10→11→12 sequentially, running tests after each step.