Troubleshooting Guide
This guide covers common issues and their solutions when working with Tenanto.
Table of Contents
- Docker Issues
- Installation Problems
- Database Issues
- Authentication Problems
- Multi-Tenancy Issues
- Billing/Stripe Issues
- Queue/Worker Issues
- Performance Issues
- API Issues
- Filament Panel Issues
Docker Issues
Containers Won't Start
Symptoms:
docker compose upfails- Containers exit immediately
- Port binding errors
Solutions:
-
Check Docker Desktop is running
docker info # If error, start Docker Desktop application -
Check for port conflicts
# Check what's using port 80 # Linux/macOS sudo lsof -i :80 # Windows (PowerShell as Admin) netstat -ano | findstr :80 -
Stop conflicting services
# Stop Apache/Nginx if running sudo systemctl stop apache2 sudo systemctl stop nginx # Or change Tenanto ports in docker-compose.yml -
Reset Docker containers
docker compose down docker compose up -d --force-recreate
Container Exits with Code 137
Cause: Out of memory
Solution:
- Increase Docker Desktop memory allocation
- Settings > Resources > Memory > Set to at least 4GB
"Permission Denied" Errors
Symptoms:
- Can't write to storage/
- Log files not created
Solutions:
# Fix permissions (Linux/macOS)
docker compose exec app chown -R www-data:www-data storage bootstrap/cache
docker compose exec app chmod -R 775 storage bootstrap/cache
# Or from host
sudo chown -R $USER:$USER storage bootstrap/cache
chmod -R 775 storage bootstrap/cache
WSL2 Specific Issues
Docker not connecting from WSL:
-
Enable WSL2 integration in Docker Desktop:
- Settings > Resources > WSL Integration
- Enable for your distro
-
Restart WSL:
# In PowerShell as Admin wsl --shutdown
Vite Dev Server / Frontend Hot Reload
Symptom: Landing page loads but has no styles; DevTools console shows
net::ERR_CONNECTION_REFUSED for http://localhost:5273/... or a CSP
violation blocking localhost:5273.
Cause A — port 5273 is already in use by another project. Docker Compose will silently bind the wrong container when multiple services try to publish the same host port. Check with:
docker ps --format "table {{.Names}}\t{{.Ports}}" | grep 5273
If more than one container is listed, override the host port in your .env:
VITE_HOST_PORT=5274
Then recreate the vite service (no need to touch the others):
docker compose up -d --force-recreate vite
Remember to update server.origin, server.hmr.clientPort in vite.config.js
and the CSP allowances in docker/nginx/sites/tenanto.conf if you change the
port — they are hard-coded to 5273 by default. Reload nginx with
docker exec tenanto_nginx nginx -s reload after editing the CSP.
Cause B — browser cached the page before the Vite service started. Hard
refresh with Ctrl+Shift+R (or Cmd+Shift+R on macOS).
Symptom: Vite container keeps restarting, logs show EACCES when running
npm ci.
Cause: The named volume tenanto_vite_node_modules is owned by a user
from a previous project. Remove and recreate:
docker compose down
docker volume rm tenantodev_tenanto_vite_node_modules 2>/dev/null || true
docker compose up -d
Symptom: Blade/CSS edits don't reload in the browser on WSL2.
Cause: File system events from Windows → WSL2 → container bind mounts are
unreliable. Vite already polls (watch.usePolling: true in vite.config.js).
If polling is still too slow, lower the interval from 300 to 150 ms in
vite.config.js and restart the vite service.
Installation Problems
"Class Not Found" Errors
Solutions:
# Regenerate autoload
docker compose exec app composer dump-autoload
# Clear all caches
docker compose exec app php artisan optimize:clear
# If still failing, reinstall dependencies
docker compose exec app rm -rf vendor
docker compose exec app composer install
"APP_KEY" Missing
Solution:
docker compose exec app php artisan key:generate
NPM Build Fails
Solutions:
-
Clear npm cache
docker compose exec app npm cache clean --force docker compose exec app rm -rf node_modules docker compose exec app npm install -
Check Node version
docker compose exec app node -v # Should be 20.x or higher -
Memory issues during build
# Increase Node memory docker compose exec app NODE_OPTIONS="--max-old-space-size=4096" npm run build
Composer Memory Exhausted
Solution:
# Increase PHP memory limit
docker compose exec app php -d memory_limit=-1 /usr/bin/composer install
Database Issues
Connection Refused
Symptoms:
- "SQLSTATE[HY000] [2002] Connection refused"
- Can't run migrations
Solutions:
-
Check database is running
docker compose ps # db container should show "Up" -
Verify .env settings
# Docker setup DB_CONNECTION=pgsql DB_HOST=db # Container name, not localhost! DB_PORT=5432 DB_DATABASE=tenanto DB_USERNAME=tenanto DB_PASSWORD=secret -
Wait for database to be ready
# Database may take a few seconds to start docker compose logs db # Look for "database system is ready to accept connections" -
Test connection manually
docker compose exec db psql -U tenanto -d tenanto -c "SELECT 1"
Migration Fails
Symptoms:
- "Table already exists"
- "Column not found"
Solutions:
-
Fresh migration (development only)
docker compose exec app php artisan migrate:fresh --seed -
Check migration status
docker compose exec app php artisan migrate:status -
Rollback and retry
docker compose exec app php artisan migrate:rollback docker compose exec app php artisan migrate
"Unique Constraint Violation" on Seeding
Cause: Seeder already ran
Solution:
# Fresh database with seed
docker compose exec app php artisan migrate:fresh --seed
Authentication Problems
Can't Login to Admin Panel
Symptoms:
- Login form rejects credentials
- Redirects back to login
Solutions:
-
Verify default credentials
- Email:
[email protected] - Password:
password
- Email:
-
Check user exists and has correct role
docker compose exec app php artisan tinker >>> User::where('email', '[email protected]')->first() >>> # Check tenant_id is NULL for system admin -
Reset password
docker compose exec app php artisan tinker >>> $user = User::where('email', '[email protected]')->first(); >>> $user->password = bcrypt('newpassword'); >>> $user->save();
Session Not Persisting
Symptoms:
- Logged out on page refresh
- "419 Page Expired" errors
Solutions:
-
Check session configuration
SESSION_DRIVER=redis SESSION_DOMAIN=.tenanto.local -
Clear session data
docker compose exec app php artisan session:table docker compose exec app php artisan migrate # Or if using Redis docker compose exec redis redis-cli FLUSHDB -
Check CSRF token
- Ensure
@csrfis in all forms - Check browser cookies are enabled
- Ensure
API Token Not Working
Symptoms:
- 401 Unauthorized responses
- Token rejected
Solutions:
-
Check Authorization header format
Authorization: Bearer your-token-here -
Verify token exists
docker compose exec app php artisan tinker >>> PersonalAccessToken::where('token', hash('sha256', 'your-plain-token'))->first() -
Check token expiration
# .env - token lifetime in minutes (default: 7 days) SANCTUM_TOKEN_EXPIRATION=10080
Multi-Tenancy Issues
Tenant Not Found (404)
Symptoms:
- Subdomain returns 404
- "Tenant not found" error
Solutions:
-
Check DNS/hosts file
# /etc/hosts or C:\Windows\System32\drivers\etc\hosts 127.0.0.1 acme.tenanto.local -
Verify tenant exists and is active
docker compose exec app php artisan tinker >>> Tenant::where('slug', 'acme')->first() >>> # Check is_active = true -
Check tenancy mode
// config/tenancy.php 'mode' => 'subdomain', // or 'domain' or 'both' -
Clear tenant cache
docker compose exec app php artisan cache:clear
Data Leaking Between Tenants
CRITICAL SECURITY ISSUE
Immediate Steps:
-
Verify global scope is applied
docker compose exec app php artisan tinker >>> app()->bound('currentTenant') >>> # Should return true when in tenant context -
Check model uses BelongsToTenant trait
class YourModel extends Model { use BelongsToTenant; } -
Run tenant isolation tests
docker compose exec app php artisan test --filter=TenantIsolation -
Check for withoutGlobalScopes usage
- Search codebase for
withoutGlobalScopes - Should ONLY be used in admin context
- Search codebase for
Tenant User Can't Access Panel
Solutions:
-
Check user belongs to tenant
docker compose exec app php artisan tinker >>> $user = User::find(1); >>> $user->tenant_id // Should match tenant -
Check user has required role
>>> $user->roles->pluck('name') >>> # Should include 'owner', 'admin', or 'member' -
Verify Spatie permission team is set
- Middleware should set
setPermissionsTeamId($tenant->id)
- Middleware should set
Billing/Stripe Issues
Webhooks Not Received
Symptoms:
- Subscription status not updating
- No webhook logs
Solutions:
-
Check webhook URL in Stripe Dashboard
- Should be:
https://yourdomain.com/stripe/webhook
- Should be:
-
Verify webhook secret
STRIPE_WEBHOOK_SECRET=whsec_xxx -
Test webhook locally with Stripe CLI
stripe listen --forward-to localhost/stripe/webhook -
Check webhook logs
docker compose exec app tail -f storage/logs/laravel.log | grep -i stripe
"No Such Customer" Error
Cause: Tenant doesn't have Stripe customer ID
Solution:
docker compose exec app php artisan tinker
>>> $tenant = Tenant::find(1);
>>> $tenant->createAsStripeCustomer();
Subscription Not Creating
Solutions:
-
Check Stripe API keys
STRIPE_KEY=pk_test_xxx STRIPE_SECRET=sk_test_xxx -
Verify price IDs exist in Stripe
STRIPE_PRICE_BASIC=price_xxx -
Check Stripe logs
- Stripe Dashboard > Developers > Logs
Queue/Worker Issues
Jobs Not Processing
Symptoms:
- Emails not sending
- Background tasks stuck
Solutions:
-
Check queue worker is running
docker compose ps # 'queue' container should be "Up" -
Check Redis connection
docker compose exec redis redis-cli PING # Should return "PONG" -
View failed jobs
docker compose exec app php artisan queue:failed -
Retry failed jobs
docker compose exec app php artisan queue:retry all -
Restart queue worker
docker compose restart queue
Jobs Failing Silently
Solution: Check logs
docker compose exec app tail -f storage/logs/laravel.log
docker compose logs queue
Horizon Dashboard Shows "Inactive"
Solutions:
-
Restart Horizon
docker compose exec app php artisan horizon:terminate docker compose restart queue -
Check Horizon configuration
docker compose exec app php artisan horizon:status
Performance Issues
Slow Page Loads
Diagnosis:
# Enable query logging
docker compose exec app php artisan tinker
>>> DB::enableQueryLog();
>>> // Navigate to slow page
>>> DB::getQueryLog();
Common Causes & Solutions:
-
N+1 Queries
- Use eager loading:
->with(['relation']) - Use
->withCount()for counts
- Use eager loading:
-
Missing indexes
- Check
EXPLAINon slow queries - Add indexes for WHERE/ORDER BY columns
- Check
-
Cache not enabled
CACHE_STORE=redis
High Memory Usage
Solutions:
-
Use chunking for large datasets
Model::chunk(100, function ($records) { // Process }); -
Clear caches regularly
docker compose exec app php artisan cache:clear
Redis Memory Full
Solution:
docker compose exec redis redis-cli INFO memory
docker compose exec redis redis-cli FLUSHDB
API Issues
429 Too Many Requests
Cause: Rate limit exceeded
Solutions:
-
Wait and retry - Default limits:
- Auth endpoints: 10/minute
- General API: 60/minute
- Read operations: 120/minute
-
For testing, increase limits in
app/Providers/AppServiceProvider.php
CORS Errors
Symptoms:
- "Access-Control-Allow-Origin" errors in browser console
Solutions:
-
Configure allowed origins
CORS_ALLOWED_ORIGINS=https://yourfrontend.com -
Check config/cors.php
'allowed_origins' => explode(',', env('CORS_ALLOWED_ORIGINS', '')),
500 Internal Server Error
Diagnosis:
# Check Laravel logs
docker compose exec app tail -100 storage/logs/laravel.log
# Check PHP errors
docker compose logs app
Filament Panel Issues
Resources Not Showing
Solutions:
-
Check user has permission
docker compose exec app php artisan tinker >>> $user->can('view_projects') -
Clear Filament cache
docker compose exec app php artisan filament:cache-components -
Check resource is registered
- Verify resource is in correct Panel Provider
Form Validation Not Working
Solution: Clear views
docker compose exec app php artisan view:clear
Widgets Not Loading
Solutions:
-
Check Livewire is working
docker compose exec app php artisan livewire:discover -
Check browser console for JavaScript errors
-
Clear all caches
docker compose exec app php artisan optimize:clear
Getting More Help
If your issue isn't covered here:
-
Check the logs first
docker compose exec app tail -f storage/logs/laravel.log -
Search existing documentation
-
Contact support
- Email: your configured
SUPPORT_EMAILaddress - Include: PHP version, error logs, steps to reproduce
- Email: your configured
Quick Reference Commands
# Clear all caches
docker compose exec app php artisan optimize:clear
# Restart everything
docker compose down && docker compose up -d
# Check service status
docker compose ps
# View logs
docker compose logs -f app
# Database fresh start (DESTROYS DATA)
docker compose exec app php artisan migrate:fresh --seed
# Run tests
docker compose exec app php artisan test
# Check queue status
docker compose exec app php artisan queue:failed