Skip to content

Extension Troubleshooting

Use this when a package extension does not appear, does not run, or behaves differently between admin and public requests. Start with the smallest check that proves whether Capell can see the package, then move toward the specific runtime.

For focused debugging paths, use:

ProblemRunbook
Composer, manifest, or provider discoveryDebugging package discovery
Admin pages, fields, actions, widgets, settingsDebugging admin extensions
Public output, cache bypasses, unsafe HTMLDebugging public output
Marketplace connection, verification, heartbeatDebugging Marketplace

Run these before changing code:

Terminal window
composer dump-autoload
php artisan optimize:clear
php artisan list capell
php artisan capell:package-cache:clear

If the package contributes admin configurators or widgets, also run:

Terminal window
php artisan capell:admin-clear-cache
php artisan capell:admin-cache-configurators
php artisan capell:admin-cache-widgets

Confirm the package service provider is loaded through Composer discovery, the host app’s provider list, or the package’s capell.json provider entries. A missing provider is the most common reason every downstream extension point appears broken.

SymptomLikely causeCheckFix
php artisan list capell does not show package commandsComposer autoload or provider discovery is stalecomposer show capell-app/<package> and composer dump-autoload -oReinstall/update the package, fix composer.json autoload, then clear Laravel and Capell package caches.
Package appears in Composer but not in Capell package statecapell.json is missing, invalid, or not loadedInspect capell.json; run package manifest tests when availableFix manifest name, providers, surfaces, and version constraints, then run php artisan capell:package-cache:clear.
Install/setup runs but package data is missingInstall command skipped settings migrations or package setup actionsCheck package install command output and php artisan migrate:statusRegister settings migrations and run setup through Actions rather than writing from providers.
SymptomLikely causeCheckFix
Resource/page/widget does not show in navigationContribution was not registered, permission denies access, or navigation is intentionally suppressedCheck the package admin provider, AdminBridge::register(), and the user’s permissionsPrefer AdminBridgeRegistrar::resource(), page(), widget(), or dashboardWidget(). Re-run capell:admin-install when permissions changed.
An Extensions page edit action is missingThe page was registered as a normal page instead of an extension pageSearch for registerExtensionPage(...)Register the package control page with CapellAdmin::registerExtensionPage($packageName, PageClass::class).
Dashboard widget is registered but disabledWidgets are available but admin settings hide themCheck Admin settings and widget defaultsUse registerOverviewStat() for small metrics or enable the widget through Admin settings or setEnabledWidgets().
Form fields are missingWrong extender tag, wrong hook enum, or configurator cache is staleCheck tags such as PageSchemaExtender::TAG and SiteSchemaExtender::TAGTag the extender in the provider or AdminBridgeRegistrar::schemaExtender(), then clear/cache admin configurators.
Header/table actions are missingExtender targets the wrong surfaceCheck whether the target is page, site, resource, or Extensions pageUse the matching extender tag: PageHeaderActionExtender, SiteHeaderActionExtender, ResourceHeaderActionExtender, PageTableExtender, or ExtensionsPageActionRegistry.
User fields or relation managers are missingUser schema bridge/extender does not support the current contextCheck UserSchemaExtender::supports() or the package UserResourceBridge::isEnabled() logicUse AbstractUserSchemaExtender for no-op defaults, and test the resolver with the same user model/context used by the resource.
Publish panel content is missingThe package used a page schema extender instead of PublishPanelExtenderSearch for PublishPanelExtender::TAGTag a PublishPanelExtender and return a View, HTML string, or null from extendPanel().
Admin route works on one host but not anotherCAPELL_ADMIN_PATH or CAPELL_ADMIN_DOMAIN is cachedphp artisan config:show capell-admin.path and php artisan config:show capell-admin.domainUpdate env/config and run php artisan optimize:clear. Signed preview URLs must be regenerated after host/path changes.
SymptomLikely causeCheckFix
Settings group is absentSettings class or schema was not registeredSearch for SettingsSchemaRegistry::registerSettingsClass() and register()Register both the settings class and schema, or use AdminBridgeRegistrar::settingsClass() and settingsSchema().
Settings page label/icon is genericMetadata is missingSearch for registerMetadata(new SettingsGroupMetadata(...))Register metadata with translated labels and the correct group key.
Settings save fails on fresh installsSettings migration did not run or is not idempotentCheck database/settings/ and install/setup command registrationAdd guarded settings migrations and cover fresh install plus upgrade paths.
Settings appear in tests but not browserConfig/package cache is stale or provider boot order differsClear caches and inspect provider registration timingRegister settings in boot() or after resolving SettingsSchemaRegistry when package load order matters.

| Symptom | Likely cause | Check | Fix | | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | Render hook output is absent | Wrong location, scenario, target, or provider timing | Search for RenderHookRegistry::register(...); compare location/scenario/target with the Blade call | Register in boot() and match the exact RenderHookLocation, scenario, and target used by the component. | | Public page route catches package/admin URLs | Path was not reserved before the frontend fallback route | Inspect ReservedFrontendPathRegistry registrations and route order | Reserve exact paths or prefixes from the package provider, then clear route/config cache. | | Public package route returns 404 | Route file/provider was not loaded or frontend fallback owns the path first | php artisan route:list | grep <path> | Load the package route provider and reserve the path if it should not fall through to page rendering. | | Public page middleware runs in the wrong order | Package middleware was appended/prepended without considering frontend resolution | Inspect FrontendRouteMiddlewareRegistry::all() in a focused test | Use insertAfter() or insertBefore() around a known middleware instead of broad prepend/append. | | Component alias resolves to a raw Blade name | Component was registered with Blade/Livewire but not FrontendComponentRegistry | Check FrontendComponentRegistryInterface::has() and hasReference() | Register a stable key and aliases through FrontendComponentRegistryInterface. | | Frontend rule condition never matches | Condition key differs from the stored settings/runtime rule | Search for FrontendRuleCondition::key() and the stored rule key | Register the condition class and keep the key stable; cover it with a direct condition test. | | HTML cache bypasses a page | Public output contains authoring markers, field paths, model IDs, package internals, or signed admin URLs | Check response headers for X-Frontend-Cache: BYPASS; inspect rendered HTML as anonymous user | Remove authoring state from public Blade. Frontend authoring must load after page load from an authenticated admin beacon. | | Tailwind classes are missing | Package sources/imports were not registered or Vite cannot resolve a symlinked dependency | Run the frontend asset report command when installed; inspect TailwindAssetsRegistry::toReport() in tests | Register sources/imports through TailwindAssetsRegistry, install missing npm packages, or add a narrow Vite alias. | | Page shows old content | Static HTML or fragment cache is stale | Check queue workers, public/page-cache, and cache invalidation registrations | Run php artisan capell:html-cache:clear; if using the HTML cache package, run php artisan capell:static-site; keep queue workers running. |

SymptomLikely causeCheckFix
Model changes do not clear package outputThe model was not registered with CacheInvalidationRegistrySearch for registerDependency(Model::class, ...)Register exact cache keys where possible. Wildcard patterns intentionally flush the whole capell-frontend tag.
Invalidation works locally but not productionQueue worker, cache driver, or tag support differsCheck QUEUE_CONNECTION, cache driver, and worker logsUse a supported cache driver for tagged cache behavior and run workers for async invalidation.
Fragment output remains staleFragment uses a different key/surrogate key than invalidation codeCompare @cache(...) keys with invalidation callsAlign surrogate keys and avoid ad hoc cache key construction in Blade.
SymptomLikely causeCheckFix
Package does not appear in browser installerComposer cannot resolve it or manifest metadata is incompletecomposer show capell-app/<package> --available; inspect capell.json provider/scopes/kindFix Composer auth/repositories and manifest metadata, then clear package/config cache.
Package appears but cannot be selected with a themeTheme key/package metadata is missing or requirements are unmetCheck kind, themeKey, extends, and requirements in capell.jsonKeep theme metadata in the manifest and make the package installable before opening /install.
Install guide patch is missingPatch was not registered in PatchRegistry or probe() says it is not applicableSearch registerPatches() and inspect the patch reason()Register the patch, keep probe() idempotent, and cover the host-file state with a patch test.
Catalogue loads but install is blockedSite is not connected or install authorization is denied by Capell AppOpen Marketplace diagnostics and heartbeat stateConnect a Capell account, resolve diagnostics, then request authorization again.
api/registration-sessions route is missingMarketplace API URL uses the old unversioned pathphp artisan config:show capell-marketplace.marketplace.base_urlUse https://capell.app/api/v1, then run php artisan config:clear.
Domain verification failsExact host mismatch, expired challenge, or public .well-known path blockedFetch the challenge URL from outside the serverVerify the exact production host, remove auth/CDN blocks, and restart verification.
Account linking callback failsStale approval URL, expired session, invalid state, or missing APP_URL hostLatest marketplace_account_connection_sessions.last_errorSet APP_URL, clear config, and start a fresh account connection from the same browser session.
Heartbeat fails after account linkingNo public webhook URL, no instance, or Marketplace API unreachablePhoneHomeAction::lastFailureMessage() and latest marketplace_instances rowSet CAPELL_MARKETPLACE_WEBHOOK_URL when needed, confirm network access, and run heartbeat again.

Add or update a focused test when the issue crossed one of these boundaries:

  • package discovery, manifest validation, or install/setup behavior;
  • admin resources, settings, widgets, extenders, permissions, or navigation;
  • public rendering, route fallback, render hooks, cache output, or Tailwind assets;
  • marketplace authorization, account linking, diagnostics, or domain verification.

For public output, test anonymous and non-admin responses directly. Cached/static HTML must match the same safe output and must not contain authoring markers, model IDs, field paths, selectors, signed admin URLs, or package internals.