Common Pitfalls
The problems Bagisto developers run into again and again, each as the symptom, its cause in the code, and the fix. To investigate something that isn't listed here, start with Debugging Tips.
Installation and Setup
PHP Version and Extensions
- Symptom:
composer installfails with a platform error, or every request stops with a PHP version error. - Cause: Bagisto 2.5 requires PHP 8.4 (
"php": "^8.4"incomposer.json; the locked dependencies need 8.4.1 or later), while 2.4 accepts 8.3 or 8.4. A second, older PHP binary often comes first on thePATH.composer.jsonalso requires thecalendar,curl,intl,mbstring,openssl,pdo,pdo_mysqlandtokenizerextensions, and a PostgreSQL store needspdo_pgsql. - Fix: Check the PHP that Composer runs with
php -vandcomposer check-platform-reqs, which lists anything missing.
Storage Link and APP_URL
- Symptom: Channel logos, category images or theme section images under
/storageare broken; or, often after the store moves to another domain, only channel logos and category images point at the wrong host. - Cause: Every file served from
/storageneeds thepublic/storagelink tostorage/app/public. Channel logos and category images are also built withStorage::url(), which takes its host fromAPP_URL(thepublicdisk'surlinconfig/filesystems.php), so it must match the URL you browse, port included. Theme section images and resized images under/cache/…use the request's own host. - Fix: Run
php artisan storage:linkand correctAPP_URL;php artisan aboutshows the URL and whether the link exists.
Running bagisto:install on an Existing Store
- Symptom: Every order, customer and product is gone.
- Cause:
php artisan bagisto:installsets up a new store: it generates a newAPP_KEYand runsdb:wipeandmigrate:freshbefore seeding. - Fix: Upgrade with
php artisan migrate, neverbagisto:install. See Upgrade Guide.
migrate:fresh Without Seeding
- Symptom: The storefront and the admin stop working after
php artisan migrate:fresh. - Cause: The tables are empty: no channel, locale, currency, customer group or admin, which the storefront and the admin read on every request.
- Fix: Run
php artisan db:seed; the application'sDatabaseSeederruns the installer's seeders.
Database
Code That Only Ever Ran on MySQL
- Symptom: A package that works on MySQL fails on PostgreSQL with type, grouping or syntax errors, or searches that no longer match.
- Cause: Bagisto runs on MySQL 8.0, MariaDB 10.11 and PostgreSQL 16 (2.4 has no PostgreSQL support). PostgreSQL has a case-sensitive
LIKE, truncatesCAST(… AS CHAR)to one character, rejects ungrouped selected columns and empty strings in typed columns, and returns booleans astrueandfalse. - Fix: Route database-specific SQL through
db_grammar()and cast boolean columns; see Database Compatibility.
Migration Order
- Symptom: A migration in your package fails to add a foreign key to a core table.
- Cause: Laravel sorts the migrations of every package into one list by file name, whichever service provider loaded them.
- Fix: Give the migration a timestamp later than the core migration that creates the table.
Switching File Storage
- Symptom: After choosing Amazon S3 or Cloudflare R2 in the admin's File Management configuration, existing product and category images are missing.
- Cause: New uploads go to the new disk, and the storefront looks for existing files there too, but nothing copies them.
- Fix: Copy
storage/app/publicto the bucket before switching; see File Storage.
Package Development
Editing Core Packages
- Symptom: Your change disappears or conflicts on the next Bagisto update.
- Cause: It was made inside
packages/Webkul/<Package>orvendor/. - Fix: Put it in your own package: override the view from a theme, listen to the event, merge configuration from your service provider, or replace the model through Concord. See Event Listeners and Models.
Registering a Package
- Symptom: The package's classes aren't found, or its routes, views, translations, migrations or models never load.
- Cause: One of its three registrations is missing: the namespace in
autoloadin the rootcomposer.json(classes), the service provider inbootstrap/providers.php(routes, views, translations, migrations), or, for a package with models, theModuleServiceProviderinconfig/concord.php(models). - Fix: Add the missing one, and run
composer dump-autoloadafter editingcomposer.json. See Package Development and Models.
Admin Routes Need an ACL Entry
- Symptom: A restricted admin role gets
401on your route, while the default administrator can open it. - Cause: The
adminmiddleware,Webkul\User\Http\Middleware\Bouncer, refuses any admin route that isn't mapped in anacl.phpand isn't in its short list of routes every admin may use. It applies to every role whose permission type isn't All, so testing as the default administrator hides the problem. - Fix: Add an ACL entry for every admin route, and use the same key with
bouncer()->hasPermission()in controllers and views; see Access Control List.
Saving a Product Outside the Admin Controller
Symptom: A product written from your own code keeps its old price, stock or page on the storefront.
Cause: The admin's
ProductControllerdispatchescatalog.product.update.beforeandcatalog.product.update.afteraround its save, and the listeners on theafterevent refresh the flat row, queue the indexing, reindex catalog rule prices, record the Omnibus price and clear the page and catalog API caches. Eloquent, the query builder and evenProductRepository::update()skip all of that.Fix: Fire the same pair around your write:
phpEvent::dispatch('catalog.product.update.before', $id); $product = $this->productRepository->update($data, $id); Event::dispatch('catalog.product.update.after', $product);php artisan event:list --event=catalog.product.update.afterlists the listeners.
Front End and Assets
Assets Not Rebuilt
- Symptom: A CSS, JavaScript or Vue change doesn't show in the browser.
- Cause: Admin, Shop and Installer each have their own
vite.config.jsand npm scripts; the Admin and Shop builds are written topublic/themes/admin/default/buildandpublic/themes/shop/default/build. - Fix: Run
npm run buildfrom that package's directory, such aspackages/Webkul/Shop, ornpm run devto serve the assets from Vite's development server while you work.
Missing Tailwind Classes
- Symptom: A Tailwind class, or an icon, renders with no style.
- Cause: Tailwind generates only the classes it finds in the files it scans. The
source("../../../")argument at the top of the Admin and Shopapp.csscovers that package'ssrc/directory, so a class used only in a theme underresources/themesor another package isn't generated, and neither is a class name built at runtime. Icon classes are declared inapp.csstoo. - Fix: Add an
@sourceline for the extra path, or an@source inline(...)entry for runtime class names, then rebuild. On 2.4 (Tailwind 3) use thecontentarray andsafelistin the package'stailwind.config.js.
Caching
Stale Configuration After .env Changes
- Symptom: An edit to
.envorconfig/has no effect. - Cause:
php artisan config:cachehas been run, and the cached configuration wins over.envuntil it's cleared. - Fix: Run
php artisan optimize:clear.
Full Page Cache Serving Old Pages
- Symptom: A guest sees an old storefront page that a signed-in customer doesn't.
- Cause: The change fired no event the full page cache listens for, such as an import or a direct database write. Signed-in customers are never served cached pages (
packages/Webkul/FPC/src/CacheProfiles/FullPageCacheProfile.php), so the problem only reproduces as a guest. - Fix: Run
php artisan responsecache:clear.--urlforgets only one channel, locale and currency variant; see Configure Full Page Cache.
Queues
The Sync Queue in Production
- Symptom: Product saves are slow, and mail and indexing hold up the admin's requests.
- Cause:
.env.examplesetsQUEUE_CONNECTION=sync, which runs every job inside the request, so a product save runs its inventory, price and search indexing before the page returns. - Fix: Set
QUEUE_CONNECTIONtodatabaseorredisand run a worker on both queues core uses,php artisan queue:work --queue=default,broadcastable. See Queues, Jobs and Scheduling.
Mail
SMTP Settings from the Admin Are Ignored
- Symptom: Mail doesn't use the SMTP host and credentials saved in the admin's email configuration.
- Cause: Those settings (
emails.configure.smtp.*) are read only by thebagisto-dynamic-smtpmailer thatWebkul\Core\Providers\DynamicMailServiceProviderregisters, which falls back toconfig('mail.mailers.smtp')for any empty setting.MAIL_MAILERin.envnaming another mailer bypasses it, and the admin's configuration screen shows a notice saying so. - Fix: Set
MAIL_MAILER=bagisto-dynamic-smtp, as.env.exampledoes.
Admin and Debugging
Changing the Admin URL
- Symptom: The admin still answers on the old prefix, or returns
404on the new one. - Cause:
APP_ADMIN_URLsets the prefix of every admin route (config('app.admin_url'),adminby default), and the configuration and routes are cached. - Fix: Run
php artisan optimize:clearafter changing it. The storefront maintenance page never applies under that prefix.
Setting APP_DEBUG_ALLOWED_IPS
- Symptom: Every request and artisan command stops with a class-not-found error for the old Debugbar facade.
- Cause: Any value in
APP_DEBUG_ALLOWED_IPSmakesAppServiceProvidercall a facade that the installed debug bar no longer ships. - Fix: Leave it empty and control the debug bar with
APP_DEBUGandDEBUGBAR_ENABLED; see Debugging Tips.
Search
Search Index Out of Date
- Symptom: Elasticsearch results, price sorting or filters don't match the catalog after attribute, category or customer group changes, or after the nightly price reindex.
- Cause: A document holds the product as it was last indexed. Attribute, category and customer group changes and the scheduled price reindexes don't rewrite it; see Search Engines.
- Fix: Run
php artisan indexer:index --type=search --mode=full(--type=elasticon 2.4); it does nothing unless an external search engine is enabled. For connection problems, see Configure Elasticsearch.
Channels and Locales
Settings Are per Channel and Locale
- Symptom: A setting saved in the admin reads as its default in code, or on another channel.
- Cause: Many settings are saved per channel, per locale, or both, and
core()->getConfigData()reads the current channel and locale, falling back to the field's default when nothing is saved there. - Fix: Save the setting for the channel and locale that reads it, or pass the channel and locale codes to
core()->getConfigData().
Maintenance Mode Is One Switch Plus a Flag per Channel
- Symptom: A channel's maintenance page doesn't appear, or saving one channel brings every channel back up.
- Cause: The storefront shows its maintenance page only when Laravel's maintenance mode is on and the current channel's
is_maintenance_onis set (Webkul\Core\Http\Middleware\PreventRequestsDuringMaintenance); the admin URL and the channel's allowed IPs always get through.php artisan downsets the flag on every channel and turns maintenance mode on;php artisan upclears both. Saving a channel turns maintenance mode on or off to match that channel alone, so saving one with maintenance off brings back every channel. - Fix: After changing maintenance on one channel, check the others and confirm the state with
php artisan about. On more than one web server, share the state withAPP_MAINTENANCE_DRIVER=cache; see Configure Load Balancing.
Tests
Tests See Your Store's Data
- Symptom: A test that counts rows or reads the first row of a listing fails, or a test fails with "table not found".
- Cause: The Pest suite runs against the database in
.env, inside a transaction per test, and a normal run never migrates. - Fix: Assert on the records the test created, and run
php artisan migratefirst when your package adds a table; see Testing with Pest.
Stale Parallel Test Databases
- Symptom:
vendor/bin/pest --parallelfails after a seeder or an existing migration changed, although the code is right. - Cause: The
_test_Ndatabases are kept between runs and only migrated forward. - Fix: Run
vendor/bin/pest --parallel --recreate-databases.
The Translations Check Fails for a New Package
- Symptom:
php artisan bagisto:translations:checkreports missing locale folders for your package, or never checks it. - Cause: It expects every supported locale folder in each package directly under
packages/Webkul, and ignores packages anywhere else. - Fix: Add every locale folder; see Coding Standards.
Related Pages
- Debugging Tips: the tools for a problem that isn't listed here.
- Database Compatibility: writing SQL that runs on MySQL, MariaDB and PostgreSQL.
- Configure Full Page Cache: the page cache's store, checks and clearing.
