Laravel Eloquent ORM: What is it and Why is it a Game-Changer?
Discover the power of Eloquent ORM for database interactions.
As a Laravel developer, encountering errors is an inevitable part of the development process. While error messages can be frustrating, they're actually incredibly helpful diagnostic tools that point you toward solutions. This comprehensive guide covers the most common Laravel error messages, explains what they mean, and provides practical solutions to fix them.
Error Context: Occurs during Laravel installation or when running Artisan commands.
PHP Fatal error: Uncaught Error: Class 'Illuminate\Foundation\Application' not found
Root Causes:
Solutions:
# 1. Install Composer dependencies
composer install
# 2. Regenerate autoload files
composer dump-autoload
# 3. Update Composer
composer self-update
# 4. Clear Composer cache
composer clear-cache
# 5. Delete vendor folder and reinstall (if corrupted)
rm -rf vendor
rm composer.lock
composer install
# 6. Check PHP version compatibility
php --version
# Laravel 10 requires PHP 8.1+
Prevention:
// composer.json - Specify PHP version
{
"require": {
"php": "^8.1",
"laravel/framework": "^10.0"
}
}
Error Context: When accessing Laravel app without setting APP_KEY.
RuntimeException: No application encryption key has been specified.
Solutions:
# 1. Generate application key
php artisan key:generate
# 2. Copy .env.example to .env (if missing)
cp .env.example .env
# 3. Manually set APP_KEY in .env
# Generate a key:
php artisan key:generate --show
# Copy output to .env:
APP_KEY=base64:your_generated_key_here
# 4. Clear config cache
php artisan config:clear
php artisan cache:clear
Automated Setup Script:
#!/bin/bash
# setup.sh - Automated Laravel setup
echo "Setting up Laravel application..."
# Check if .env exists
if [ ! -f .env ]; then
echo "Creating .env file..."
cp .env.example .env
fi
# Generate application key
if grep -q "APP_KEY=" .env; then
if grep -q "APP_KEY=base64:" .env; then
echo "APP_KEY already set."
else
echo "Generating application key..."
php artisan key:generate
fi
else
echo "APP_KEY not found in .env, adding..."
php artisan key:generate
fi
# Set permissions
chmod -R 755 storage bootstrap/cache
# Install dependencies
composer install --no-interaction --prefer-dist --optimize-autoloader
echo "Setup complete!"
Error Context: When APP_KEY format is invalid.
Illuminate\Encryption\MissingAppKeyException
The only supported ciphers are AES-128-CBC and AES-256-CBC
Solutions:
# 1. Generate proper key format
php artisan key:generate --force
# 2. Verify .env format
# Correct format:
APP_KEY=base64:rAnDoMkEyHeRe64ChArAcTeRs==
# 3. Check for special characters or line breaks
cat .env | grep APP_KEY
# 4. Manual fix if needed
# Generate base64 key:
openssl rand -base64 32
# Add to .env:
APP_KEY=base64:generated_key_here
Error Context: Database connection issues.
SQLSTATE[HY000] [2002] Connection refused
SQLSTATE[HY000] [2002] No such file or directory
Diagnosis Script:
<?php
// database_test.php
try {
$pdo = new PDO(
'mysql:host=' . env('DB_HOST') . ';port=' . env('DB_PORT'),
env('DB_USERNAME'),
env('DB_PASSWORD')
);
echo "✅ Database connection successful!\n";
} catch (PDOException $e) {
echo "❌ Database connection failed: " . $e->getMessage() . "\n";
echo "Host: " . env('DB_HOST') . "\n";
echo "Port: " . env('DB_PORT') . "\n";
echo "User: " . env('DB_USERNAME') . "\n";
}
Solutions:
# 1. Check database service status
# MySQL
sudo systemctl status mysql
# or
sudo service mysql status
# PostgreSQL
sudo systemctl status postgresql
# 2. Start database service
sudo systemctl start mysql
sudo service mysql start
# 3. Verify credentials in .env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1 # Use 127.0.0.1 instead of localhost
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=your_password
# 4. Test connection via command line
mysql -u root -p -h 127.0.0.1
# 5. Grant database privileges
mysql -u root -p
CREATE DATABASE laravel;
CREATE USER 'laravel_user'@'127.0.0.1' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON laravel.* TO 'laravel_user'@'127.0.0.1';
FLUSH PRIVILEGES;
Production Fix:
// config/database.php - Add connection retry logic
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_TIMEOUT => 5, // Connection timeout
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]) : [],
],
Error Context: Cache/session driver not available.
Class 'Memcached' not found
Predis\Connection\ConnectionException: Connection refused
Solutions:
# For Memcached (Ubuntu/Debian)
sudo apt-get install php-memcached memcached
sudo systemctl restart php8.2-fpm
sudo systemctl enable memcached
sudo systemctl start memcached
# For Redis
sudo apt-get install redis-server php-redis
sudo systemctl enable redis-server
sudo systemctl start redis-server
# Verify installation
php -m | grep -i memcached
php -m | grep -i redis
# Test Redis connection
redis-cli ping # Should return "PONG"
# Alternative: Use file/database cache temporarily
# In .env:
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_CONNECTION=sync
Error Context: Controller namespace issues.
Illuminate\Contracts\Container\BindingResolutionException
Target class [App\Http\Controllers\HomeController] does not exist.
Solutions:
// 1. Check controller namespace
// Correct location: app/Http/Controllers/HomeController.php
namespace App\Http\Controllers;
class HomeController extends Controller
{
public function index()
{
return view('home');
}
}
// 2. Check route definition
// web.php - Correct:
use App\Http\Controllers\HomeController;
Route::get('/', [HomeController::class, 'index']);
// OLD syntax (Laravel 7 and below):
Route::get('/', 'HomeController@index');
// 3. Run controller make command
php artisan make:controller HomeController --invokable
// 4. Check autoload
composer dump-autoload
// 5. Clear cached routes
php artisan route:clear
php artisan config:clear
Debugging Script:
// debug_controller.php
$controller = 'App\Http\Controllers\HomeController';
if (class_exists($controller)) {
echo "✅ Controller class exists.\n";
$methods = get_class_methods($controller);
echo "Available methods: " . implode(', ', $methods) . "\n";
} else {
echo "❌ Controller class not found.\n";
// Check file location
$file = app_path('Http/Controllers/HomeController.php');
if (file_exists($file)) {
echo "✅ File exists at: $file\n";
echo "Check namespace in file.\n";
} else {
echo "❌ File not found at: $file\n";
}
}
Error Context: Using undefined named routes.
InvalidArgumentException
Route [profile] not defined.
Solutions:
// 1. Check route definition
// Define route with name:
Route::get('/user/profile', [ProfileController::class, 'show'])
->name('profile');
// 2. List all named routes
php artisan route:list --name-only
// 3. Check Blade syntax
// Correct:
<a href="{{ route('profile') }}">Profile</a>
// 4. For optional parameters:
Route::get('/user/{id}/profile', ...)->name('profile');
// Usage:
route('profile', ['id' => 1]);
// 5. Debug route helper
@php
try {
$url = route('profile');
echo "Route URL: $url";
} catch (Exception $e) {
echo "Route error: " . $e->getMessage();
}
@endphp
Route Debugging Helper:
// app/Helpers/RouteHelper.php
if (!function_exists('route_exists')) {
function route_exists($name)
{
try {
app('router')->getRoutes()->getByName($name);
return true;
} catch (Exception $e) {
return false;
}
}
}
// Usage in Blade:
@if(route_exists('profile'))
<a href="{{ route('profile') }}">Profile</a>
@endif
Error Context: Form submissions failing CSRF protection.
419 | Page Expired
Debugging Approach:
<!-- 1. Ensure CSRF token is included -->
<form method="POST" action="/submit">
@csrf <!-- This is required -->
<!-- Alternative for JavaScript apps -->
<meta name="csrf-token" content="{{ csrf_token() }}">
</form>
<!-- 2. For AJAX requests -->
<script>
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
</script>
Solutions:
// 1. Check session configuration
// .env - Ensure same domain for session cookie
SESSION_DOMAIN=yourdomain.com
SANCTUM_STATEFUL_DOMAINS=yourdomain.com
// 2. Verify session driver
SESSION_DRIVER=file # or database, redis
// 3. Clear session files
php artisan session:clear
// 4. Check file permissions
chmod -R 755 storage/framework/sessions
// 5. Exclude routes from CSRF (use cautiously)
// app/Http/Middleware/VerifyCsrfToken.php
protected $except = [
'stripe/*',
'webhook/*',
'api/*',
];
// 6. Verify timezone settings
APP_TIMEZONE=UTC
CSRF Troubleshooting Script:
// routes/web.php - Debug route
Route::get('/debug/csrf', function () {
return response()->json([
'token' => csrf_token(),
'session_id' => session()->getId(),
'session_data' => session()->all(),
'cookies' => request()->cookies->all(),
]);
});
Error Context: Wrong HTTP method for route.
Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
The GET method is not supported for this route. Supported methods: POST.
Solutions:
// 1. Check route method mismatch
// Route definition:
Route::post('/submit', [FormController::class, 'submit']);
// Form should use POST:
<form method="POST" action="/submit">
// 2. Use appropriate route methods
Route::match(['get', 'post'], '/submit', ...);
Route::any('/submit', ...); // Accepts any method
Route::resource('photos', PhotoController::class); // RESTful
// 3. Check for redirects that change method
// Wrong:
return redirect()->route('submit')->withInput();
// 4. Debug current request
dd(request()->method(), request()->fullUrl());
// 5. Handle form method spoofing for PUT/PATCH/DELETE
<form method="POST">
@method('PUT')
@csrf
</form>
Route Method Debugger:
// app/Http/Middleware/LogRequests.php
public function handle($request, Closure $next)
{
\Log::info('Request Method: ' . $request->method(), [
'url' => $request->fullUrl(),
'route' => $request->route() ? $request->route()->getName() : null,
'supported_methods' => $request->route() ?
$request->route()->methods() : []
]);
return $next($request);
}
Error Context: 404 errors with pretty page.
404 Not Found
Debugging Solutions:
// 1. Check route definition
php artisan route:list
// 2. Verify controller method exists
public function show($id)
{
// Method should match route
}
// 3. Check parameter binding
Route::get('/users/{user}', [UserController::class, 'show']);
// Controller method:
public function show(User $user) // Implicit binding
// 4. Custom 404 page
// Create: resources/views/errors/404.blade.php
// Return custom response in App\Exceptions\Handler:
public function render($request, Throwable $exception)
{
if ($exception instanceof ModelNotFoundException) {
return response()->view('errors.404', [], 404);
}
return parent::render($request, $exception);
}
// 5. Fallback route (place at end of routes file)
Route::fallback(function () {
return response()->view('errors.404', [], 404);
});
Error Context: Missing database table.
Illuminate\Database\QueryException
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'laravel.users' doesn't exist
Solutions:
# 1. Run migrations
php artisan migrate
# 2. Check migration status
php artisan migrate:status
# 3. Fresh migration (deletes all data!)
php artisan migrate:fresh
# 4. For specific table
php artisan make:migration create_users_table
# Then migrate
# 5. Check .env database name
DB_DATABASE=laravel
# 6. Manually verify table exists
mysql -u root -p laravel -e "SHOW TABLES;"
# 7. Reset and re-run
php artisan migrate:reset
php artisan migrate
Migration Troubleshooting Script:
// app/Console/Commands/CheckDatabase.php
class CheckDatabase extends Command
{
protected $signature = 'db:check';
public function handle()
{
$tables = [
'users', 'password_resets', 'migrations',
'failed_jobs', 'personal_access_tokens'
];
foreach ($tables as $table) {
try {
DB::table($table)->count();
$this->info("✅ Table '$table' exists");
} catch (Exception $e) {
$this->error("❌ Table '$table' missing: " . $e->getMessage());
}
}
}
}
Error Context: Missing column in database table.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'email_verified_at' in 'field list'
Solutions:
# 1. Create migration for new column
php artisan make:migration add_email_verified_at_to_users_table --table=users
# 2. Migration file
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->timestamp('email_verified_at')->nullable();
});
}
# 3. Run migration
php artisan migrate
# 4. Check if column exists in model fillable
protected $fillable = ['email_verified_at'];
# 5. Rollback and re-migrate if needed
php artisan migrate:rollback --step=1
php artisan migrate
Column Checker Helper:
// app/Helpers/DatabaseHelper.php
if (!function_exists('table_has_column')) {
function table_has_column($table, $column)
{
$schema = \DB::getSchemaBuilder();
return $schema->hasColumn($table, $column);
}
}
// Usage:
if (!table_has_column('users', 'email_verified_at')) {
// Create migration
}
Error Context: Unique constraint violation.
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'email@example.com' for key 'users_email_unique'
Solutions:
// 1. Check for existing record before creating
$user = User::where('email', $email)->first();
if ($user) {
// Update existing
$user->update($data);
} else {
// Create new
User::create($data);
}
// 2. Use updateOrCreate
User::updateOrCreate(
['email' => $email],
$data
);
// 3. Use firstOrCreate
$user = User::firstOrCreate(
['email' => $email],
$data
);
// 4. Check database unique constraints
SHOW INDEX FROM users WHERE Non_unique = 0;
// 5. For bulk operations, ignore duplicates
DB::table('users')->insertOrIgnore([
['email' => 'test@example.com', 'name' => 'Test'],
]);
// 6. Reset auto-increment if needed
ALTER TABLE users AUTO_INCREMENT = 1;
Unique Constraint Handler:
// app/Traits/HasUniqueOperations.php
trait HasUniqueOperations
{
public static function safeCreate(array $attributes)
{
try {
return static::create($attributes);
} catch (QueryException $e) {
if (str_contains($e->getMessage(), 'Duplicate entry')) {
// Extract duplicate value from error
preg_match("/Duplicate entry '(.+)' for key/", $e->getMessage(), $matches);
$duplicateValue = $matches[1] ?? 'unknown';
// Find existing record
return static::where($attributes)->first();
}
throw $e;
}
}
}
Error Context: Invalid date format for database.
SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '2023-13-45' for column 'created_at'
Solutions:
// 1. Use Carbon for date handling
use Carbon\Carbon;
$user->created_at = Carbon::parse($dateString);
$user->created_at = now(); // Current datetime
$user->created_at = today(); // Today at midnight
// 2. Validate date format
$request->validate([
'birth_date' => 'required|date',
'start_date' => 'required|date_format:Y-m-d',
'end_date' => 'required|date|after:start_date',
]);
// 3. Set date format in model
protected $casts = [
'birth_date' => 'date:Y-m-d',
'created_at' => 'datetime:Y-m-d H:i:s',
];
// 4. MySQL strict mode might be too strict
// In config/database.php:
'connections' => [
'mysql' => [
'strict' => false, // Disable strict mode
// Or set specific modes
'modes' => [
'STRICT_TRANS_TABLES',
'NO_ZERO_IN_DATE',
'NO_ZERO_DATE',
'ERROR_FOR_DIVISION_BY_ZERO',
'NO_AUTO_CREATE_USER',
'NO_ENGINE_SUBSTITUTION'
],
],
],
Date Validation Middleware:
// app/Http/Middleware/ValidateDates.php
class ValidateDates
{
public function handle($request, Closure $next)
{
$dateFields = ['birth_date', 'start_date', 'end_date'];
foreach ($dateFields as $field) {
if ($request->has($field)) {
try {
Carbon::parse($request->input($field));
} catch (\Exception $e) {
return response()->json([
'error' => "Invalid date format for {$field}",
'expected' => 'YYYY-MM-DD'
], 422);
}
}
}
return $next($request);
}
}
Error Context: Inserting without required field.
SQLSTATE[HY000]: General error: 1364 Field 'name' doesn't have a default value
Solutions:
// 1. Check model fillable properties
class User extends Model
{
protected $fillable = ['name', 'email', 'password'];
// Or use guarded (less secure)
protected $guarded = [];
}
// 2. Set default values in migration
Schema::create('users', function (Blueprint $table) {
$table->string('name')->default(''); // Set default
$table->string('name')->nullable(); // Allow null
});
// 3. Set default in model
protected $attributes = [
'name' => 'Guest',
'status' => 'active',
];
// 4. Check database column definition
SHOW CREATE TABLE users;
// 5. Disable strict mode (temporary fix)
// config/database.php
'connections' => [
'mysql' => [
'strict' => false,
],
],
Field Validator Script:
// app/Console/Commands/ValidateModelFields.php
class ValidateModelFields extends Command
{
protected $signature = 'validate:fields {model}';
public function handle()
{
$modelClass = 'App\\Models\\' . $this->argument('model');
$model = new $modelClass;
$table = $model->getTable();
$columns = \DB::getSchemaBuilder()->getColumnListing($table);
$this->info("Columns for $table:");
foreach ($columns as $column) {
$type = \DB::getSchemaBuilder()->getColumnType($table, $column);
$nullable = \DB::getDoctrineColumn($table, $column)->getNotnull() ? 'NOT NULL' : 'NULL';
$default = \DB::getDoctrineColumn($table, $column)->getDefault();
$this->line(" $column: $type $nullable (Default: $default)");
}
}
}
Error Context: Missing Blade template file.
InvalidArgumentException
View [welcome] not found.
Solutions:
// 1. Check view file exists
// Should be: resources/views/welcome.blade.php
// 2. Check view path
// Correct: return view('welcome');
// For subdirectories: return view('admin.dashboard');
// 3. Clear view cache
php artisan view:clear
php artisan cache:clear
// 4. Check view namespace (for packages)
// If using package views: return view('package::view.name');
// 5. List all views
php artisan view:list
// 6. Create view if missing
php artisan make:view welcome
// Or manually create file
// 7. Verify file permissions
chmod -R 755 resources/views
View Finder Debugger:
// Debug route to check view paths
Route::get('/debug/views', function () {
$finder = app('view')->getFinder();
$paths = $finder->getPaths();
$hints = $finder->getHints();
return [
'paths' => $paths,
'namespaces' => $hints,
'all_views' => collect(File::allFiles(resource_path('views')))
->map(function ($file) {
return $file->getRelativePathname();
})
];
});
Error Context: Variable not passed to view.
ErrorException
Undefined variable: users
Solutions:
// 1. Pass variable to view
return view('users.index', ['users' => $users]);
// or
return view('users.index')->with('users', $users);
// or
return view('users.index', compact('users'));
// 2. Use optional helper in Blade
{{ $variable ?? 'Default' }}
// 3. Check variable name spelling
// Controller: ['users' => $data]
// View: should use $users not $user
// 4. Use @isset directive
@isset($users)
{{ count($users) }}
@endisset
// 5. Share variable globally
// In AppServiceProvider:
view()->share('siteName', 'My Site');
// 6. Debug all available variables
@php
dump(get_defined_vars());
@endphp
View Data Inspector Middleware:
// app/Http/Middleware/LogViewData.php
class LogViewData
{
public function handle($request, Closure $next)
{
$response = $next($request);
if ($response instanceof \Illuminate\View\View) {
\Log::debug('View Data:', [
'view' => $response->getName(),
'data' => array_keys($response->getData()),
]);
}
return $response;
}
}
Error Context: Accessing property on null object.
ErrorException
Trying to get property 'name' of non-object
Solutions:
{{-- 1. Use null coalescing operator --}}
{{ $user->name ?? 'Guest' }}
{{-- 2. Use optional() helper --}}
{{ optional($user)->name }}
{{-- 3. Check with @if --}}
@if($user)
{{ $user->name }}
@else
Guest
@endif
{{-- 4. Use Eloquent's default model --}}
// In route model binding
Route::get('/user/{user}', function (User $user = null) {
return view('profile', compact('user'));
});
{{-- 5. Use findOrFail in controller --}}
$user = User::findOrFail($id);
{{-- 6. Use find with default --}}
$user = User::find($id) ?? new User(['name' => 'Guest']);
Null-safe Operations Trait:
// app/Traits/NullSafe.php
trait NullSafe
{
public function safe($property, $default = null)
{
$value = $this;
foreach (explode('.', $property) as $segment) {
if (is_null($value)) {
return $default;
}
if (is_array($value)) {
$value = $value[$segment] ?? null;
} elseif (is_object($value)) {
$value = $value->$segment ?? null;
} else {
return $default;
}
}
return $value ?? $default;
}
}
// Usage in Blade:
{{ $user->safe('profile.avatar.url', '/default.png') }}
Error Context: Infinite recursion in views or functions.
Fatal error: Maximum function nesting level of '100' reached, aborting!
Solutions:
// 1. Increase xdebug.max_nesting_level
// In php.ini:
xdebug.max_nesting_level = 200
// 2. Check for recursive relationships
// Model:
public function parent()
{
return $this->belongsTo(Category::class, 'parent_id');
}
public function children()
{
return $this->hasMany(Category::class, 'parent_id');
}
// In view (CAUSES RECURSION):
@foreach($categories as $category)
@include('category', ['category' => $category])
@endforeach
// Fix: Limit depth
public function getNestedCategories($parentId = null, $depth = 0, $maxDepth = 5)
{
if ($depth >= $maxDepth) {
return collect();
}
return Category::where('parent_id', $parentId)
->with(['children' => function ($query) use ($depth, $maxDepth) {
$query->with(['children' => ...]); // Limited depth
}])
->get();
}
// 3. Check for circular includes
// view1.blade.php includes view2.blade.php
// view2.blade.php includes view1.blade.php (INFINITE!)
// 4. Disable xdebug temporarily
php -d xdebug.mode=off artisan serve
// 5. Use iterative approach instead of recursive
function processTreeIteratively($items)
{
$result = [];
$stack = [$items];
while (!empty($stack)) {
$current = array_pop($stack);
foreach ($current as $item) {
$result[] = $item;
if ($item->children) {
$stack[] = $item->children;
}
}
}
return $result;
}
Error Context: Memory limit exceeded.
Fatal error: Allowed memory size of 134217728 bytes exhausted
Solutions:
// 1. Increase memory limit
// In .env:
PHP_MEMORY_LIMIT=256M
// In php.ini:
memory_limit = 256M
// Temporary increase in code:
ini_set('memory_limit', '256M');
// 2. Optimize queries
// BAD: Loads all records
$users = User::all(); // Could be millions!
// GOOD: Use pagination
$users = User::paginate(100);
// GOOD: Use chunking for processing
User::chunk(1000, function ($users) {
foreach ($users as $user) {
// Process
}
});
// 3. Use cursor for large datasets
foreach (User::cursor() as $user) {
// Process one at a time
}
// 4. Unset large variables
$largeData = // ... big data
process($largeData);
unset($largeData); // Free memory
// 5. Use generator functions
function processUsers()
{
foreach (User::cursor() as $user) {
yield processUser($user);
}
}
// 6. Monitor memory usage
\Log::info('Memory usage: ' . memory_get_usage(true));
Memory Profiler Middleware:
// app/Http/Middleware/MemoryProfiler.php
class MemoryProfiler
{
public function handle($request, Closure $next)
{
$startMemory = memory_get_usage(true);
$startTime = microtime(true);
$response = $next($request);
$endMemory = memory_get_usage(true);
$endTime = microtime(true);
$memoryUsed = $endMemory - $startMemory;
$timeUsed = $endTime - $startTime;
\Log::info('Memory Profiler', [
'memory_used' => round($memoryUsed / 1024 / 1024, 2) . 'MB',
'time_used' => round($timeUsed, 3) . 's',
'url' => $request->fullUrl(),
'peak_memory' => round(memory_get_peak_usage(true) / 1024 / 1024, 2) . 'MB',
]);
if ($memoryUsed > 50 * 1024 * 1024) { // 50MB
\Log::warning('High memory usage detected');
}
return $response;
}
}
Error Context: Missing or misconfigured authentication guard.
InvalidArgumentException
Authentication guard [web] is not defined.
Solutions:
// 1. Check config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
// 2. Check .env for session driver
SESSION_DRIVER=file # or database, redis
// 3. Verify middleware usage
// Correct:
Route::middleware(['auth'])->group(...);
// For API:
Route::middleware(['auth:api'])->group(...);
// 4. Clear config cache
php artisan config:clear
php artisan cache:clear
// 5. Check Auth facade alias
// In config/app.php:
'aliases' => [
'Auth' => Illuminate\Support\Facades\Auth::class,
],
// 6. Verify authentication scaffolding is installed
// If using Laravel UI:
composer require laravel/ui
php artisan ui bootstrap --auth
// If using Breeze:
composer require laravel/breeze
php artisan breeze:install
Auth Configuration Validator:
// app/Console/Commands/ValidateAuth.php
class ValidateAuth extends Command
{
protected $signature = 'auth:validate';
public function handle()
{
$config = config('auth');
$this->info('Authentication Configuration:');
$this->line('Guards: ' . json_encode(array_keys($config['guards'])));
$this->line('Providers: ' . json_encode(array_keys($config['providers'])));
// Test each guard
foreach ($config['guards'] as $guardName => $guardConfig) {
try {
Auth::guard($guardName)->check();
$this->info("✅ Guard '$guardName' is properly configured");
} catch (\Exception $e) {
$this->error("❌ Guard '$guardName' error: " . $e->getMessage());
}
}
}
}
Error Context: Login authentication failure.
The provided credentials do not match our records.
Debugging Solutions:
// 1. Check user exists
$user = User::where('email', $email)->first();
dd($user); // Check if null
// 2. Verify password
if ($user && Hash::check($password, $user->password)) {
// Password matches
}
// 3. Check if user is active
if ($user && $user->active) {
// User is active
}
// 4. Debug authentication attempt
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// Success
} else {
\Log::warning('Failed login attempt', [
'email' => $email,
'ip' => request()->ip(),
'user_agent' => request()->userAgent(),
]);
}
// 5. Check throttle settings
// In LoginController:
$this->maxAttempts = 5;
$this->decayMinutes = 1;
// 6. Verify email case sensitivity
$user = User::whereRaw('LOWER(email) = ?', [strtolower($email)])->first();
// 7. Check for whitespace in input
$email = trim(request('email'));
$password = trim(request('password'));
Login Debugger Route:
Route::post('/debug/login', function (Request $request) {
$email = $request->email;
$password = $request->password;
$user = \App\Models\User::where('email', $email)->first();
if (!$user) {
return response()->json([
'error' => 'User not found',
'email' => $email,
'user_count' => \App\Models\User::where('email', 'like', "%{$email}%")->count()
], 404);
}
$passwordMatch = \Hash::check($password, $user->password);
return response()->json([
'user_found' => true,
'user_id' => $user->id,
'email' => $user->email,
'password_match' => $passwordMatch,
'user_active' => $user->active,
'hashed_input' => \Hash::make($password),
'stored_hash' => $user->password,
]);
});
Error Context: API authentication failure.
Unauthenticated.
Solutions:
// 1. Check Sanctum/Passport installation
// For Sanctum:
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
// 2. Add Sanctum middleware to API routes
// In app/Http/Kernel.php:
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
// 3. Create API token
$user = User::find(1);
$token = $user->createToken('api-token')->plainTextToken;
// 4. Send token in header
Authorization: Bearer {token}
// 5. For SPA authentication
// In .env:
SANCTUM_STATEFUL_DOMAINS=localhost:3000,localhost:8080
// 6. Check CORS configuration
// In config/cors.php:
'paths' => ['api/*'],
'allowed_origins' => ['http://localhost:3000'],
'supports_credentials' => true,
// 7. Verify token abilities
$user->createToken('api-token', ['server:update']);
// In middleware:
if (!$request->user()->tokenCan('server:update')) {
abort(403);
}
API Auth Debug Middleware:
// app/Http/Middleware/DebugApiAuth.php
class DebugApiAuth
{
public function handle($request, Closure $next)
{
\Log::debug('API Auth Debug', [
'has_token' => $request->bearerToken() ? 'Yes' : 'No',
'token' => $request->bearerToken(),
'user' => $request->user() ? $request->user()->id : 'None',
'headers' => $request->headers->all(),
]);
return $next($request);
}
}
Error Context: Authorization failure with Gates/Policies.
AuthorizationException
This action is unauthorized.
Solutions:
// 1. Check policy registration
// In AuthServiceProvider:
protected $policies = [
Post::class => PostPolicy::class,
];
// 2. Verify policy method exists
class PostPolicy
{
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
}
// 3. Check authorization in controller
$this->authorize('update', $post);
// 4. Use Gate for complex logic
if (Gate::allows('update-post', $post)) {
// Authorized
}
// 5. Define gate in AuthServiceProvider
Gate::define('update-post', function (User $user, Post $post) {
return $user->id === $post->user_id;
});
// 6. Debug authorization
\Log::debug('Authorization check', [
'user_id' => auth()->id(),
'post_user_id' => $post->user_id,
'policy_method' => 'update',
'result' => auth()->user()->can('update', $post),
]);
// 7. Use @can in Blade
@can('update', $post)
<a href="{{ route('posts.edit', $post) }}">Edit</a>
@endcan
Authorization Debugger:
// app/Helpers/AuthHelper.php
if (!function_exists('debug_auth')) {
function debug_auth($ability, $arguments = [])
{
$user = auth()->user();
if (!$user) {
return [
'authenticated' => false,
'message' => 'No authenticated user'
];
}
try {
$result = $user->can($ability, ...$arguments);
return [
'authenticated' => true,
'user_id' => $user->id,
'ability' => $ability,
'arguments' => $arguments,
'result' => $result,
'policies' => Gate::abilities(),
];
} catch (\Exception $e) {
return [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
];
}
}
}
Error Context: File upload issues.
Illuminate\Http\Exceptions\PostTooLargeException
The file "" was not uploaded
Solutions:
// 1. Increase upload limits
// In .env:
UPLOAD_MAX_FILESIZE=10M
POST_MAX_SIZE=12M
// In php.ini:
upload_max_filesize = 10M
post_max_size = 12M
max_file_uploads = 20
// 2. Check form encoding
<form method="POST" enctype="multipart/form-data">
// 3. Validate file upload
$request->validate([
'avatar' => 'required|image|max:2048', // 2MB
'document' => 'required|file|mimes:pdf,doc,docx|max:5120', // 5MB
]);
// 4. Handle file upload
if ($request->hasFile('avatar')) {
$path = $request->file('avatar')->store('avatars', 'public');
$user->avatar = $path;
}
// 5. Create symbolic link for public disk
php artisan storage:link
// 6. Check file permissions
chmod -R 755 storage
chmod -R 755 public/storage
// 7. For large files, use chunked uploads
// JavaScript frontend + Laravel chunk handling
File Upload Validator:
// app/Http/Middleware/ValidateUpload.php
class ValidateUpload
{
public function handle($request, Closure $next)
{
if ($request->hasFile('file')) {
$file = $request->file('file');
// Check PHP limits
$maxUpload = ini_get('upload_max_filesize');
$maxPost = ini_get('post_max_size');
if ($file->getSize() > $this->convertToBytes($maxUpload)) {
return response()->json([
'error' => "File too large. Max upload size: $maxUpload"
], 422);
}
// Check disk space
$freeSpace = disk_free_space(storage_path());
if ($file->getSize() > $freeSpace * 0.9) {
return response()->json([
'error' => 'Insufficient disk space'
], 422);
}
}
return $next($request);
}
private function convertToBytes($size)
{
$unit = strtolower(substr($size, -1));
$size = (int) $size;
switch ($unit) {
case 'g': return $size * 1024 * 1024 * 1024;
case 'm': return $size * 1024 * 1024;
case 'k': return $size * 1024;
default: return $size;
}
}
}
Error Context: File storage path issues.
League\Flysystem\FileNotFoundException
File not found at path: ...
Solutions:
// 1. Check if file exists before operations
if (Storage::disk('public')->exists('avatars/1.jpg')) {
$url = Storage::disk('public')->url('avatars/1.jpg');
}
// 2. Use safe file operations
try {
$contents = Storage::get('file.jpg');
} catch (\Exception $e) {
// Handle missing file
$contents = null;
}
// 3. Verify storage configuration
// In config/filesystems.php:
'disks' => [
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
],
],
// 4. Recreate storage link
php artisan storage:link --force
// 5. Check file permissions
sudo chmod -R 755 storage/app/public
sudo chown -R www-data:www-data storage
// 6. For missing files, provide default
$avatarUrl = $user->avatar ?
Storage::url($user->avatar) :
'/images/default-avatar.jpg';
Storage Health Check:
// app/Console/Commands/CheckStorage.php
class CheckStorage extends Command
{
protected $signature = 'storage:check';
public function handle()
{
$disks = config('filesystems.disks');
foreach ($disks as $diskName => $config) {
$this->info("Checking disk: $diskName");
try {
$disk = Storage::disk($diskName);
// Test write
$testFile = 'test_' . time() . '.txt';
$disk->put($testFile, 'test');
// Test read
$content = $disk->get($testFile);
// Test delete
$disk->delete($testFile);
$this->info("✅ Disk '$diskName' is working");
// Check free space for local disks
if ($config['driver'] === 'local') {
$free = disk_free_space($config['root']);
$total = disk_total_space($config['root']);
$percent = round(($total - $free) / $total * 100, 2);
$this->line(" Space used: {$percent}%");
$this->line(" Free: " . round($free / 1024 / 1024, 2) . "MB");
}
} catch (\Exception $e) {
$this->error("❌ Disk '$diskName' error: " . $e->getMessage());
}
}
}
}
Error Context: Queue configuration issues.
InvalidArgumentException
Queue connection [redis] is not defined.
Solutions:
// 1. Check queue configuration
// In .env:
QUEUE_CONNECTION=redis # or database, sync, sqs
// In config/queue.php:
'connections' => [
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],
],
// 2. Create jobs table (for database driver)
php artisan queue:table
php artisan migrate
// 3. Install and configure Redis
sudo apt-get install redis-server
sudo systemctl enable redis-server
sudo systemctl start redis-server
// 4. Check Redis connection
redis-cli ping
// 5. Clear config cache
php artisan config:clear
// 6. Test queue connection
\Queue::connection()->getPdo(); // For database
// or
\Queue::getConnection()->ping(); // For Redis
Queue Configuration Validator:
// app/Console/Commands/ValidateQueue.php
class ValidateQueue extends Command
{
protected $signature = 'queue:validate';
public function handle()
{
$connection = config('queue.default');
$this->info("Default queue connection: $connection");
$config = config("queue.connections.$connection");
if (!$config) {
$this->error("Configuration for '$connection' not found");
$this->line("Available connections: " .
implode(', ', array_keys(config('queue.connections'))));
return;
}
$this->info("Configuration:");
foreach ($config as $key => $value) {
$this->line(" $key: " . json_encode($value));
}
// Test connection
try {
$queue = \Queue::connection($connection);
if (method_exists($queue, 'getPdo')) {
$queue->getPdo();
$this->info("✅ Database connection successful");
} elseif (method_exists($queue, 'ping')) {
$queue->ping();
$this->info("✅ Redis connection successful");
}
} catch (\Exception $e) {
$this->error("❌ Connection failed: " . $e->getMessage());
}
}
}
Error Context: Job max attempts exceeded.
Illuminate\Queue\MaxAttemptsExceededException
Job has been attempted too many times.
Solutions:
// 1. Set appropriate retry attempts
class ProcessPodcast implements ShouldQueue
{
public $tries = 3; // Max attempts
public $maxExceptions = 3; // Max exceptions
public $timeout = 120; // Seconds
public $backoff = 60; // Seconds between retries
// Dynamic backoff
public function backoff()
{
return [1, 5, 10, 30]; // Exponential backoff
}
// Retry until
public function retryUntil()
{
return now()->addMinutes(10);
}
// Handle failure
public function failed(Throwable $exception)
{
// Send notification, log, etc.
}
}
// 2. Implement failed method
public function failed(Throwable $exception)
{
// Send notification
\Log::error('Job failed after max attempts', [
'job' => get_class($this),
'exception' => $exception->getMessage(),
]);
// Mark record as failed
$this->podcast->update(['processing_status' => 'failed']);
}
// 3. Use exponential backoff
public $backoff = 60; // Seconds between retries
// Or dynamic backoff
public function backoff()
{
return [1, 5, 10, 30]; // Exponential backoff
}
// 4. Check why job is failing
public function handle()
{
try {
// Job logic
} catch (\Exception $e) {
\Log::error('Job error', [
'job' => get_class($this),
'data' => $this->data,
'exception' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
throw $e; // Re-throw for retry
}
}
// 5. Monitor failed jobs
php artisan queue:failed
// Retry failed jobs
php artisan queue:retry all
Job Monitor:
// app/Console/Commands/MonitorJobs.php
class MonitorJobs extends Command
{
protected $signature = 'jobs:monitor';
public function handle()
{
$failedJobs = \DB::table('failed_jobs')->count();
$pendingJobs = \DB::table('jobs')->count();
$this->info("Pending jobs: $pendingJobs");
$this->info("Failed jobs: $failedJobs");
if ($failedJobs > 10) {
$this->error("High number of failed jobs!");
// List recent failures
$recent = \DB::table('failed_jobs')
->orderBy('failed_at', 'desc')
->limit(5)
->get();
foreach ($recent as $job) {
$payload = json_decode($job->payload);
$this->line("Failed: " . $payload->displayName);
$this->line("At: " . $job->failed_at);
$this->line("Error: " . $job->exception);
$this->line("---");
}
}
// Check for stuck jobs
$stuckJobs = \DB::table('jobs')
->where('available_at', '<', now()->subMinutes(30))
->count();
if ($stuckJobs > 0) {
$this->warn("Found $stuckJobs stuck jobs");
}
}
}
Error Context: Cache configuration issues.
InvalidArgumentException
Cache store [array] is not defined.
Solutions:
// 1. Check cache configuration
// In .env:
CACHE_DRIVER=file # or redis, database, array
// In config/cache.php:
'stores' => [
'array' => [
'driver' => 'array',
'serialize' => false,
],
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache/data'),
],
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
],
],
// 2. Clear config cache
php artisan config:clear
php artisan cache:clear
// 3. Check Redis connection (if using redis)
// In .env:
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
// 4. Test cache connection
try {
Cache::put('test', 'value', 1);
$value = Cache::get('test');
echo "Cache working: $value";
} catch (\Exception $e) {
echo "Cache error: " . $e->getMessage();
}
// 5. Use file cache as fallback
if (app()->environment('local')) {
config(['cache.default' => 'file']);
}
// 6. Check file permissions for file cache
chmod -R 755 storage/framework/cache
Cache Tester Command:
// app/Console/Commands/TestCache.php
class TestCache extends Command
{
protected $signature = 'cache:test';
public function handle()
{
$driver = config('cache.default');
$this->info("Testing cache driver: $driver");
// Test 1: Basic put/get
try {
Cache::put('test_key', 'test_value', 1);
$value = Cache::get('test_key');
if ($value === 'test_value') {
$this->info("✅ Basic cache operations working");
} else {
$this->error("❌ Cache returned wrong value: $value");
}
// Cleanup
Cache::forget('test_key');
} catch (\Exception $e) {
$this->error("❌ Cache test failed: " . $e->getMessage());
}
// Test 2: Remember
try {
$value = Cache::remember('test_remember', 1, function () {
return 'cached_value';
});
$this->info("✅ Cache remember working");
} catch (\Exception $e) {
$this->error("❌ Cache remember failed: " . $e->getMessage());
}
// Test 3: Tags (if supported)
if (in_array($driver, ['redis', 'memcached'])) {
try {
Cache::tags(['test'])->put('tagged_key', 'value', 1);
$this->info("✅ Cache tags working");
} catch (\Exception $e) {
$this->warn("⚠️ Cache tags not supported: " . $e->getMessage());
}
}
}
}
Error Context: Session initialization issue.
RuntimeException
Session store not set on request.
Solutions:
// 1. Check session configuration
// In .env:
SESSION_DRIVER=file # or database, redis, cookie
// 2. Ensure session middleware is applied
// In routes/web.php:
Route::middleware(['web'])->group(function () {
// Your routes
});
// Or in controller constructor:
public function __construct()
{
$this->middleware('web');
}
// 3. For API routes, don't use session
// Use stateless authentication instead
// 4. Clear session files
php artisan session:clear
// 5. Check file permissions
chmod -R 755 storage/framework/sessions
// 6. Manually start session
session()->start();
// 7. Debug session configuration
dd(config('session'));
// 8. Check if using correct guard
// For web authentication:
Auth::guard('web')->attempt($credentials);
// 9. Verify session driver is installed
// For database driver:
php artisan session:table
php artisan migrate
// For Redis driver:
composer require predis/predis
// or
sudo apt-get install php-redis
Session Debugger:
// app/Http/Middleware/DebugSession.php
class DebugSession
{
public function handle($request, Closure $next)
{
\Log::debug('Session Debug', [
'driver' => config('session.driver'),
'session_id' => session()->getId(),
'session_status' => session()->status(),
'session_data' => session()->all(),
'has_session' => $request->hasSession(),
'session_name' => config('session.cookie'),
]);
return $next($request);
}
}
// Or temporary debug route:
Route::get('/debug/session', function () {
return [
'session_id' => session()->getId(),
'session_data' => session()->all(),
'config' => [
'driver' => config('session.driver'),
'lifetime' => config('session.lifetime'),
'cookie' => config('session.cookie'),
],
'cookies' => request()->cookies->all(),
];
});
Error Context: Missing cache directories in production.
InvalidArgumentException
Please provide a valid cache path.
Solutions:
# 1. Create required directories
mkdir -p storage/framework/cache/data
mkdir -p storage/framework/views
mkdir -p storage/framework/sessions
mkdir -p bootstrap/cache
# 2. Set proper permissions
chmod -R 755 storage
chmod -R 755 bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache
# 3. Clear cached configuration
php artisan config:clear
php artisan cache:clear
php artisan view:clear
# 4. In production, ensure .env is configured
# Set:
APP_DEBUG=false
APP_ENV=production
# 5. Pre-create cache files
php artisan config:cache
php artisan route:cache
php artisan view:cache
# 6. Automated setup script for production
#!/bin/bash
# setup-production.sh
echo "Setting up Laravel for production..."
# Create directories
mkdir -p storage/framework/{sessions,views,cache/data}
mkdir -p bootstrap/cache
# Set permissions
chmod -R 755 storage bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache
# Optimize for production
php artisan config:cache
php artisan route:cache
php artisan view:cache
# Set production environment
sed -i 's/APP_DEBUG=true/APP_DEBUG=false/' .env
sed -i 's/APP_ENV=local/APP_ENV=production/' .env
echo "Production setup complete!"
Directory Structure Validator:
// app/Console/Commands/ValidateStructure.php
class ValidateStructure extends Command
{
protected $signature = 'structure:validate';
public function handle()
{
$requiredDirs = [
storage_path('app'),
storage_path('app/public'),
storage_path('framework'),
storage_path('framework/cache'),
storage_path('framework/cache/data'),
storage_path('framework/sessions'),
storage_path('framework/views'),
storage_path('logs'),
base_path('bootstrap/cache'),
];
$requiredFiles = [
base_path('.env'),
base_path('storage/framework/.gitignore'),
base_path('bootstrap/cache/.gitignore'),
];
$this->info("Checking directory structure...");
foreach ($requiredDirs as $dir) {
if (!is_dir($dir)) {
$this->error("❌ Missing directory: $dir");
if ($this->confirm("Create directory?")) {
mkdir($dir, 0755, true);
$this->info("✅ Created: $dir");
}
} else {
$this->info("✅ Directory exists: $dir");
// Check permissions
if (!is_writable($dir)) {
$this->warn("⚠️ Directory not writable: $dir");
}
}
}
foreach ($requiredFiles as $file) {
if (!file_exists($file)) {
$this->error("❌ Missing file: $file");
} else {
$this->info("✅ File exists: $file");
}
}
}
}
Error Context: Missing mix-manifest.json file.
InvalidArgumentException
The Mix manifest does not exist.
Solutions:
# 1. Install npm dependencies
npm install
# 2. Build assets
npm run dev # Development
npm run prod # Production
npm run build # Vite
# 3. Check if manifest file exists
ls public/mix-manifest.json
# or for Vite:
ls public/build/manifest.json
# 4. Clear cache
php artisan cache:clear
php artisan config:clear
php artisan view:clear
# 5. For Vite, ensure correct configuration
// In package.json
{
"scripts": {
"dev": "vite",
"build": "vite build"
}
}
// In vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
});
# 6. Check file permissions
chmod -R 755 public
# 7. Manual fallback (for emergencies)
// In AppServiceProvider boot method:
if (!file_exists(public_path('mix-manifest.json'))) {
file_put_contents(public_path('mix-manifest.json'), json_encode([
'/js/app.js' => '/js/app.js',
'/css/app.css' => '/css/app.css',
]));
}
Asset Builder Monitor:
// app/Console/Commands/BuildAssets.php
class BuildAssets extends Command
{
protected $signature = 'assets:build {--watch} {--prod}';
public function handle()
{
$this->info("Building assets...");
// Check if Node/npm is installed
$nodeVersion = shell_exec('node --version');
$npmVersion = shell_exec('npm --version');
if (!$nodeVersion || !$npmVersion) {
$this->error("Node.js and npm are required but not installed.");
return;
}
$this->info("Node: $nodeVersion");
$this->info("NPM: $npmVersion");
// Check package.json
if (!file_exists(base_path('package.json'))) {
$this->error("package.json not found");
return;
}
// Install dependencies
$this->info("Installing npm dependencies...");
shell_exec('npm ci --silent');
// Build assets
if ($this->option('prod')) {
$this->info("Building for production...");
shell_exec('npm run prod');
} elseif ($this->option('watch')) {
$this->info("Watching for changes...");
shell_exec('npm run dev');
} else {
$this->info("Building for development...");
shell_exec('npm run dev');
}
// Verify manifest
if (file_exists(public_path('mix-manifest.json'))) {
$this->info("✅ Mix manifest created");
$manifest = json_decode(file_get_contents(public_path('mix-manifest.json')), true);
$this->info("Assets: " . implode(', ', array_keys($manifest)));
} elseif (file_exists(public_path('build/manifest.json'))) {
$this->info("✅ Vite manifest created");
} else {
$this->error("❌ Manifest file not created");
}
}
}
1. Laravel Debugbar Integration:
composer require barryvdh/laravel-debugbar --dev
2. Custom Debug Helper:
// app/Helpers/DebugHelper.php
if (!function_exists('ld')) {
function ld(...$vars)
{
foreach ($vars as $var) {
\Log::debug(json_encode($var, JSON_PRETTY_PRINT));
}
}
}
if (!function_exists('ddq')) {
function ddq($query)
{
dd($query->toSql(), $query->getBindings());
}
}
3. Error Monitoring with Sentry:
composer require sentry/sentry-laravel
// In .env:
SENTRY_LARAVEL_DSN=https://your-sentry-dsn
4. Custom Exception Handler Enhancements:
// app/Exceptions/Handler.php
public function register()
{
$this->reportable(function (Throwable $e) {
if (app()->bound('sentry')) {
app('sentry')->captureException($e);
}
// Log with context
\Log::error($e->getMessage(), [
'exception' => get_class($e),
'file' => $e->getFile(),
'line' => $e->getLine(),
'url' => request()->fullUrl(),
'ip' => request()->ip(),
'user_id' => auth()->id(),
]);
});
}
public function render($request, Throwable $exception)
{
// Custom error pages
if ($exception instanceof ModelNotFoundException) {
return response()->view('errors.404', [], 404);
}
if ($exception instanceof \Illuminate\Auth\AuthenticationException) {
return redirect()->guest(route('login'));
}
return parent::render($request, $exception);
}
1. Pre-deployment Checklist:
// app/Console/Commands/PreDeployCheck.php
class PreDeployCheck extends Command
{
protected $signature = 'deploy:check';
public function handle()
{
$checks = [];
// Environment check
$checks[] = [
'name' => 'Environment File',
'status' => file_exists(base_path('.env')),
'message' => '.env file exists',
'fix' => 'cp .env.example .env'
];
// Key check
$checks[] = [
'name' => 'App Key',
'status' => !empty(env('APP_KEY')),
'message' => 'APP_KEY is set',
'fix' => 'php artisan key:generate'
];
// Database check
try {
\DB::connection()->getPdo();
$checks[] = [
'name' => 'Database Connection',
'status' => true,
'message' => 'Database connection successful'
];
} catch (\Exception $e) {
$checks[] = [
'name' => 'Database Connection',
'status' => false,
'message' => $e->getMessage(),
'fix' => 'Check DB credentials in .env'
];
}
// Storage permissions
$checks[] = [
'name' => 'Storage Permissions',
'status' => is_writable(storage_path()),
'message' => 'Storage directory is writable',
'fix' => 'chmod -R 755 storage'
];
// Display results
$this->table(['Check', 'Status', 'Message', 'Fix'],
array_map(function ($check) {
return [
$check['name'],
$check['status'] ? '✅' : '❌',
$check['message'],
$check['fix'] ?? ''
];
}, $checks)
);
// Exit with error if any checks failed
$failed = count(array_filter($checks, fn($c) => !$c['status']));
if ($failed > 0) {
$this->error("$failed checks failed. Fix before deployment.");
return 1;
}
$this->info("✅ All checks passed. Ready for deployment.");
return 0;
}
}
2. Automated Error Monitoring:
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
// Check for recent errors
$schedule->command('log:check-errors --hours=1')
->hourly()
->sendOutputTo(storage_path('logs/error-monitor.log'));
// Check disk space
$schedule->exec('df -h /')
->daily()
->sendOutputTo(storage_path('logs/disk-usage.log'));
// Check queue health
$schedule->command('queue:monitor')
->everyFiveMinutes();
}
3. Health Check Endpoint:
// routes/web.php
Route::get('/health', function () {
$checks = [
'database' => function () {
try {
\DB::connection()->getPdo();
return true;
} catch (\Exception $e) {
return false;
}
},
'redis' => function () {
try {
\Redis::ping();
return true;
} catch (\Exception $e) {
return false;
}
},
'storage' => function () {
return is_writable(storage_path());
},
'queue' => function () {
try {
\Queue::connection()->ping();
return true;
} catch (\Exception $e) {
return false;
}
},
];
$status = 200;
$results = [];
foreach ($checks as $name => $check) {
$result = $check();
$results[$name] = $result ? 'healthy' : 'unhealthy';
if (!$result) {
$status = 503;
}
}
return response()->json([
'status' => $status === 200 ? 'healthy' : 'unhealthy',
'timestamp' => now()->toISOString(),
'checks' => $results,
], $status);
});
Immediate Fixes (5-minute solutions)
Clear Caches:
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
composer dump-autoload
Check Permissions:
chmod -R 755 storage bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache
Environment Setup:
cp .env.example .env
php artisan key:generate
Database Issues:
php artisan migrate
php artisan db:seed
php artisan migrate:fresh --seed # WARNING: Deletes data
Assets Build:
npm install
npm run dev
php artisan storage:link
| Error Pattern | Likely Cause | Solution |
|---|---|---|
| Class not found | Autoload issue | composer dump-autoload |
| Table doesn't exist | Missing migration | php artisan migrate |
| Connection refused | Database service down | Start MySQL/PostgreSQL |
| View not found | Missing Blade file | Create view file |
| 419 Page Expired | CSRF token missing | Add @csrf to form |
| Unauthenticated | Auth middleware missing | Add auth middleware |
| Method not allowed | Wrong HTTP method | Check form method |
| Memory exhausted | Large data processing | Use pagination/chunking |
Enable Maintenance Mode:
php artisan down --retry=60 --secret=emergency-access
Check Logs:
tail -f storage/logs/laravel.log
Rollback Deployment:
git reset --hard HEAD~1
php artisan migrate:rollback
Restart Services:
sudo systemctl restart nginx
sudo systemctl restart php8.2-fpm
sudo systemctl restart supervisor
Disable Debug Mode:
APP_DEBUG=false
Understanding Laravel error messages is a critical skill for any Laravel developer. Rather than fearing errors, embrace them as valuable feedback that helps you build more robust applications. Remember these key principles:
By mastering these error resolution techniques, you'll not only fix problems faster but also write more resilient Laravel applications that gracefully handle edge cases and unexpected situations.