# Troubleshooting

| Symptom | Likely cause | Fix |
|---|---|---|
| Uploaded images give 404 | The storage symlink is missing | `php artisan storage:link`, then check `ls -la public/storage` |
| Image upload in the editor fails or does nothing | PHP upload limit, or a missing CSRF token | The alert shows the reason. Raise `upload_max_filesize` and `post_max_size`; make sure the layout has `<meta name="csrf-token" content="{{ csrf_token() }}">` |
| `Call to undefined method ... ImageManager::read()` | Code written for Intervention Image v2 or v3 | This project uses v4: `ImageManager::usingDriver()`, `decodePath()` and `encode(new WebpEncoder(...))` |
| Image processing fails with a WebP error | GD was built without WebP | Install a PHP build with WebP support (on Ubuntu `sudo apt install php8.3-gd`) |
| `Undefined variable $site` in a theme view | The view was not rendered through the `theme::` namespace, or the composer was removed | Render themed views as `view('theme::...')` and keep the `View::composer('theme::*', ...)` block in `AppServiceProvider` |
| A new theme is not listed | The folder is missing or misnamed | It must be `resources/views/themes/<slug>/` (lowercase) |
| The site looks unstyled after switching themes | `public/themes/<slug>/style.css` is missing | Create it, then hard refresh (Ctrl + Shift + R) |
| Template changes do not show | Compiled views are cached | `php artisan view:clear` |
| Menu, sidebar or site name do not update | Cached data | `php artisan cache:clear` |
| A page gives 404, or another route is hijacked | The `/{slug}` page route is not last in `routes/web.php`, or the slug is reserved | Keep it as the very last route and avoid reserved slugs |
| `HAVING clause on a non-aggregate query` (SQLite) | `having()` used without `groupBy()` | Use `whereHas()` plus `withCount()` instead |
| 403 on `/admin/...` | The user's role is too low | Change the role in Admin → Users, or run `php artisan cms:make-admin <email>` |
| Bullet lists appear as numbered lists | Content saved by an old editor version | Open the article and save it again |
| Logo or favicon does not change | Browser cache | Hard refresh. URLs carry a version number that changes when you upload |
| Images in old article bodies are broken | They were saved with an absolute `http://localhost/...` URL | Run the tinker command below |
| Times are off by hours | Timezone not set | Set `APP_TIMEZONE` and run `php artisan config:clear` |
| The docs page is empty | The `docs/` folder or files are missing | Files must be named like `01-introduction.md` and live in `docs/` |

To fix old absolute image URLs, open `php artisan tinker` and run:

```php
App\Models\Article::all()->each(fn ($a) => $a->update(['body' => preg_replace('#https?://[^/"]+/storage/#', '/storage/', $a->body)]));
```

## Getting more detail

- Application errors are written to `storage/logs/laravel.log`.
- While developing, `APP_DEBUG=true` shows the full error page.
- The browser console and network tab help with upload and asset problems.

## Reporting a bug

Open an issue with: what you did, what you expected, what happened, your PHP version, database and browser, and the relevant lines from `storage/logs/laravel.log`.
