Cookbook
Load Errors And Recovery
Extension load failures are captured so the rest of MyronCMS can continue running while the operator can see what failed. Use this recipe when an extension is registered but not loaded, its admin route is missing, or its actions do not appear.
Use Case
An extension is present under app/extensions/{vendor}/, but Installed Extensions shows:
Not loaded
or displays a latest load error.
Human Path
Open:
/extensions
Review:
- vendor,
- enabled/disabled state,
- granted scopes,
- directory presence,
- loaded/not loaded state,
- latest load error.
Depending on the failure, an administrator can:
- enable the extension,
- disable the extension,
- revoke an individual granted scope,
- return to Register Extension to create or refresh the grant.
Local code or manifest fixes still happen in the repository.
AI Path
An AI coding agent can:
- inspect
manifest.json, - fix local PHP or migration files,
- ensure route and migration paths are valid,
- run verification,
- explain what an administrator needs to review in
/extensions.
An installed MCP client must not enable the extension, grant itself scopes, revoke trust gates, or bypass CSRF/admin-only forms. Runtime recovery through Installed Extensions is human-admin-only.
How Errors Are Recorded
During MyronExtensionLoader::boot(), the loader catches manifest, migration, bootstrap, and contribution registration failures.
On failure, it:
- stores the message in memory for that boot,
- writes a row through
ExtensionScopeGrantRepository::recordLoadError(), - continues loading other extensions and core routes.
On successful load, it calls:
$this->grants->clearLoadErrors($manifest->vendor);
That clears previous persisted errors for the vendor.
How Errors Surface
Installed Extensions uses:
myronExtensionLoader()->statuses();
The status includes:
| Field | Meaning |
|---|---|
enabled | Whether the grant row is enabled. |
grantedScopes | Scopes recorded for the vendor grant. |
directoryExists | Whether the extension directory is present. |
manifestFound | Whether the manifest parsed for this boot. |
loaded | Whether the manifest exists, no load failure was recorded, and the grant is enabled. |
lastError | Latest persisted or in-memory load error message. |
The page renders load health and latest error text in the browser.
Scopes
Load recovery itself is not an MCP or action call. Extension grant and enablement are administrator workflows.
The underlying load failure can still be scope-related. If a manifest requires content.write but the grant only includes content.read, the loader records an ungranted-scope failure.
Artifacts
Admin surfaces:
/extensions/extensions/register
Database tables:
extension_scope_grantsextension_load_errors
Local files:
app/extensions/{vendor}/manifest.jsonapp/extensions/{vendor}/bootstrap.phpapp/extensions/{vendor}/migrations/*.phpapp/extensions/{vendor}/admin/routes/*.php
Safety Boundary
Do not treat a load error as permission to weaken the system. Safe recovery is to fix the local extension package or have an administrator adjust the grant.
Do not:
- edit database grant rows directly,
- remove CSRF checks,
- skip
myronRequireAdministrationAccess(), - broaden caller scopes from an MCP client,
- bypass the loader to register actions manually.
Verification
Run:
php app/tests/verify-extension-system-foundation.php
The foundation test verifies that:
- an unregistered extension is skipped,
- a registered reference extension loads,
- a bootstrap exception is recorded as a load error,
- Installed Extensions route keys resolve,
- the Extensions rail section is administrator-only.
For a real recovery, verify:
- the local fix is present,
- the extension is registered and enabled,
- the required manifest scopes are granted,
- the page no longer shows the previous load error after a successful load,
- actions or admin routes appear only if their source files and grants are valid.
Failure Modes
| Symptom | Likely cause | Safe remediation |
|---|---|---|
| Extension does not appear in runtime actions | Extension is unregistered, disabled, under-granted, or failed during boot. | Review /extensions, fix local files, and confirm grants. |
| Directory missing | Grant exists but local extension directory is absent. | Restore the local extension directory or disable the grant. |
| Manifest missing or invalid | manifest.json is absent or invalid JSON/schema. | Fix the manifest; keep vendor and directory aligned. |
| Load error mentions ungranted scope | Manifest requires a scope not granted by the operator. | Administrator reviews the grant; do not self-broaden through MCP. |
| Migration failure | Migration touched a non-prefixed table or threw. | Fix migration under {vendor}_*; rerun through normal load. |
| Bootstrap throws | PHP error or explicit exception in bootstrap.php. | Fix the bootstrap or contributed class. |
| Admin route missing | Handler file is missing or extension did not load. | Fix the route path and load state. |
| Old load error still visible | Extension has not successfully loaded since the fix. | Trigger normal runtime boot and confirm the vendor loads cleanly. |
Recovery Checklist
- Confirm the vendor directory exists.
- Validate
manifest.json. - Confirm the grant exists in
/extensions/registeror/extensions. - Confirm the extension is enabled.
- Confirm granted scopes cover manifest
requiredScopes. - Review migrations for
{vendor}_*table isolation. - Review
bootstrap.phpand contributed classes for thrown exceptions. - Run the foundation test.
- Reload Installed Extensions and confirm the old error is gone.