Skip to content

Troubleshooting

James Daley edited this page Apr 25, 2026 · 3 revisions

Troubleshooting

Start with the runtime phase where the symptom appears: discovery, compatibility, entitlement, registry resolution, lifecycle, or UI surface rendering.

Triage Flow

flowchart TD
    Symptom["Observed failure"] --> Discover{"Manifest discovered?"}
    Discover -- no --> ManifestFix["Check bundle path and JSON schema"]
    Discover -- yes --> Compatible{"Compatibility report clean?"}
    Compatible -- no --> CompatFix["Fix schema, platform, version, or capability"]
    Compatible -- yes --> Unlocked{"Entitlement unlocked?"}
    Unlocked -- no --> EntFix["Check iapProductID and provider state"]
    Unlocked -- yes --> Factory{"Registry factory found?"}
    Factory -- no --> RegFix["Register matching entryPoint"]
    Factory -- yes --> Lifecycle{"start(context) succeeds?"}
    Lifecycle -- no --> StartFix["Inspect module error logs"]
    Lifecycle -- yes --> UI{"UI visible?"}
    UI -- no --> UIFix["Check selected UI module, viewID, slot, and registry"]
    UI -- yes --> Done["Runtime path healthy"]
Loading

Common Symptoms

Symptom Likely Cause Fix
No modules discovered Manifest files are not bundled under ForsettiManifests. Check target membership and resource path.
validationFailed Manifest JSON is malformed or missing required fields. Validate JSON and compare with the schema page.
duplicateModuleID Two manifests share the same moduleID. Make module IDs globally unique.
incompatible(report:) Platform/version/capability check failed. Inspect compatibility issues and fix the manifest or policy.
moduleLocked Entitlement provider returned locked. Verify iapProductID, StoreKit state, or static unlock IDs.
notUIModule Manifest says ui or app, but factory returned a plain ForsettiModule. Return a ForsettiUIModule or ForsettiAppModule.
Active UI module not visible activeUIModuleID not selected or injected view not registered. Call setSelectedUIModule and register viewID.
Toolbar route fails Pointer/route ID missing or destination/slot unsupported. Check active OverlaySchema and host catalogs.
Module messages not received Target payload does not match subscriber module ID. Use sendModuleMessage and subscribe with the target ID.

Manifest Debug Checklist

flowchart LR
    Path["Resource path"] --> Fields["Required fields"]
    Fields --> Types["moduleType and platforms"]
    Types --> Version["Forsetti version range"]
    Version --> Caps["capabilitiesRequested"]
    Caps --> Entry["entryPoint"]
Loading

Required manifest root keys:

  • schemaVersion
  • moduleID
  • displayName
  • moduleVersion
  • moduleType
  • supportedPlatforms
  • minForsettiVersion
  • capabilitiesRequested
  • entryPoint

Logs to Check

Log Source Useful For
ConsoleForsettiLogger in debug builds Activation, deactivation, and module lifecycle messages.
ForsettiHostController.errorMessage User-visible controller failures.
ForsettiHostOverlayRouter.lastOutcome Pointer and route resolution failures.
Compatibility report Exact reason activation cannot proceed.

Recovery Pattern

  1. Reproduce with the smallest manifest and module set.
  2. Confirm the manifest loads.
  3. Confirm compatibility is clean.
  4. Confirm entitlement unlock state.
  5. Confirm the registry entry point.
  6. Confirm module lifecycle behavior.
  7. Confirm UI contribution rendering.
  8. Add a focused regression test.

Clone this wiki locally