Troubleshooting
Bridge never becomes ready
Check the bridge bootstrap first.
hostOriginsmust resolve to at least one exact trusted origin.enabled: false,killSwitchActive: true, ormode: 'production'disables the bridge.- Messages from untrusted origins are ignored before protocol parsing, so a wrong origin usually looks like silence.
Common mistakes include missing https://, forgetting a preview origin, using the wrong localhost port, or leaving a comma-separated env var blank.
Storybook manager URL loads but the preview never answers
Check both Storybook bootstraps.
initStorybookManagerRelay()must run in.storybook/manager.ts, not only in the preview iframe.- The manager relay
hostOriginsmust trust the exact Itera debugger origins that are allowed to talk to Storybook. - The preview must start
bootstrapStorybookPreviewInspectorBridge(...)andbootIterationInspectorRuntime()during.storybook/preview.tsxstartup. - Keep the manager relay bootstrapped once per manager session. If Storybook hot reload re-runs manager startup, guard it with a global bootstrapped flag instead of stacking relays.
Storybook relay cannot find the preview iframe
initStorybookManagerRelay() assumes the Storybook 10 preview iframe selector iframe#storybook-preview-iframe.
Check these first:
- confirm the manager shell still renders that iframe id
- if your Storybook wrapper replaces or nests the preview iframe, pass
previewIframeSelectororresolvePreviewIframe - keep the relay in the manager window so it can rediscover the active preview iframe after story navigation or iframe replacement
- when you need to isolate relay or discovery issues quickly, use the direct
iframe.htmlstory URL as a temporary fallback
Storybook preview trusts direct iframe.html but not the manager URL
This is usually a preview-origin setup problem.
- Keep the base
hostOriginslist focused on exact Itera host origins such as your local debugger or hosted editor origins. - Use
resolveStorybookPreviewHostOrigins({ hostOrigins, referrer: document.referrer })or passmanagerOriginexplicitly so the preview also trusts the Storybook manager origin. - Do not replace the Itera host allowlist with the Storybook origin. The preview needs both the explicit debugger host origins for direct preview use and the manager origin for proxied traffic.
- If the manager URL origin changed, reload the manager and preview so the runtime and bridge pick up the new trusted-origin state.
Direct iframe.html is still the right fallback sometimes
The manager URL is the preferred path, but direct preview URLs are still useful when:
- you are debugging relay startup or preview iframe discovery
- you intentionally want to bypass Storybook manager behavior
- your Storybook shell uses a non-standard preview iframe and you have not wired
previewIframeSelectororresolvePreviewIframeyet
React tree or props are empty
This is usually a timing problem.
- Move
bootstrapEmbeddedInspectorBridge()orinitDevEmbeddedInspectorBridge()earlier. - In Next.js, use
instrumentation-client.ts. - In Vite-style or CRA-style apps, run bootstrap before
ReactDOM.createRoot(...).
If the inline backend hook is installed after React is already interactive, the preferred fiber path can return an empty tree or start on a framework-specific fallback path until fiber data becomes available.
Vue READY arrives but the tree is empty
This usually means the bridge started too late or never got a mounted Vue app.
Check these first:
- bootstrap during client startup, not from inside a mounted Vue component tree
- call
bootstrapEmbeddedInspectorBridgeOnMount(...)orregisterVueAppOnMount(...)before or immediately aroundapp.mount(...) - if you use the low-level bridge, pair it with
mountedAppDiscovery.strategy: 'explicit-only'when you want to prove explicit registration is working
The preferred Vue contract is explicit app registration. If startup happens after mount, the runtime is more likely to rely on DOM discovery fallback.
The Vue bridge only works when DOM discovery kicks in
That means the app was not explicitly registered and the runtime fell back to DOM discovery.
DOM discovery is best-effort. It assumes:
- a connected Vue mount container
- the default
[data-v-app]marker or another configured discovery selector - a normal browser DOM app lifecycle
If the app mounts into a ShadowRoot, custom root, or lifecycle that detaches containers, switch to explicit registration and treat discovery as a safety net only.
Vue source metadata only shows a file or line: 1
That is expected without compile-time instrumentation.
Baseline Vue source support reads best-effort metadata from fields such as:
__source__filefilefileName
When only a file path is available, the runtime reports line: 1. If you need reliable file, line, and column metadata, add createVueInspectorSourceMetadataVitePlugin() from @iteraai/vue-component-inspector/vite.
The Vue Vite source metadata plugin seems to do nothing
Check the build pipeline:
- install
createVueInspectorSourceMetadataVitePlugin()beforevue()in plain Vite - in Nuxt, add the same plugin under
vite.plugins - make sure the component module is still going through the Vite transform pipeline rather than being replaced by another precompiled asset step
If the bridge still returns only best-effort file metadata, inspect a tree snapshot with includeSource: true and confirm whether the relevant node ever received column data.
Element selection never activates
The bridge and the iteration runtime are separate startup paths.
- Call
bootIterationInspectorRuntime()during startup, not only when the user opens a selection UI. - The runtime emits
runtime_readyonly after it starts. - Outside an iframe,
bootIterationInspectorRuntime()returnsnullunless you passallowSelfMessaging: true.
If the page is embedded by different parent origins during one runtime session, reload the page. The runtime pins the first accepted parent origin until it stops.
Host origin changed and messages stopped
Both startup paths care about origin state.
- The bridge only accepts messages from origins in
hostOrigins. - The iteration runtime remembers the first accepted parent origin for the lifetime of the started runtime.
If you switched editors, preview domains, Storybook manager origins, or localhost ports, update hostOrigins and reload the app.
Vue iteration selection component paths look shorter than expected
Vue component paths are contextual metadata, not a guaranteed stable identifier.
The selection runtime resolves component ancestry from Vue DOM markers first and then falls back to the nearest known component root elements. Because of that, these cases can collapse to the nearest resolvable ancestor:
- fragments
- teleported content
- slot content rendered outside the nearest owning root
- DOM nodes that outlive the component instance that created them
Use the DOM locator fields as the durable target and treat componentPath as helpful host-side context rather than the sole replay key.
Forced next, vite, or cra made React inspection worse
Use the default fiber path unless you have a specific reason not to. The framework-specific adapter targets are exported, but the normal embedded bootstrap helpers already prefer fiber and can fall back when fiber discovery is empty.