Skip to content

bug: cdp_navigation_state throws on a null bridge result and misses forwardRef NavigationContainer roots when expo-router is bundled #1031

Description

@Lykhoyda

Description

Two cdp_navigation_state failures seen on plugin 1.0.8 while a Test App switched its root between a react-navigation NavigationContainer and other roots (a second, ownerless NavigationContainer > Tab.Navigator, and a real Expo Router Tabs root) in the same bundle, with the app dev bridge (__RN_DEV_BRIDGE__) registered:

  1. When the bridge's getNavState() returns the literal string "null" (its ref's getRootState() returned undefined because the registered container was unmounted), the tool throws Cannot read properties of null (reading 'error'). The bridgeWithFallback wrapper only falls back to __RN_AGENT.getNavState() when the parsed value carries error / __agent_error, so a parsed null slips through to the tool's state.error read. Calling getRootState() on the unmounted ref also raised a React Navigation console error that opened a LogBox and covered the tab bar for the next native tap.
  2. With the bridge answering { error: "No navigation ref" } instead, the helper fiber walk (__RN_AGENT.getNavState) reported Expo Router is bundled but no navigation state was found even though a plain @react-navigation/native v7 NavigationContainer root was mounted. The walk matches fiber type.displayName || type.name === 'NavigationContainer'; v7 exports a forwardRef object whose render is NavigationContainerInner, so the container is never matched, and the expo-router presence check then wins the error message.

Both make alternate-root fixtures for issue #951 unreadable without app-side wiring.

Environment

Field Value
Plugin version 1.0.8
CDP Bridge 1.0.8
OS Darwin 25.6.0
Node.js v26.8.1
Metro session allocated, not bound (released after the run)
Session authority source_bound
Other local sessions 153
iOS Simulators 1 booted
Android Emulators 1 connected
legacy agent-device not installed
maestro-runner 1.1.24 (pinned-ok, pin-cache)

Recent Tool Activity

Telemetry: stale (last event 104 day(s) ago; capture removed with the Experience Engine, GH #200). Old events omitted.

CDP State at Time of Report

Not connected (session released after the run). During the run: connected, 0 JS errors.

Steps to Reproduce

  1. App registers globalThis.__NAV_REF__ / bridge registerNavRef with a createNavigationContainerRef() for its main NavigationContainer.
  2. Unmount that container and mount a different NavigationContainer (or ExpoRoot) in its place, keeping the old ref registered.
  3. Call cdp_navigation_state: with the stock bridge getNavState the tool throws the reading 'error' TypeError and the app shows a LogBox console error.
  4. Patch the bridge to return { error } when ref.isReady() is false and call again: the fallback walk reports the Expo Router message while a react-navigation v7 container is mounted.

Workaround

App-side: point __NAV_REF__ / the bridge ref at whichever container is mounted, and have the bridge refuse ({ error }) when ref.isReady() is false. Delivered for the Test App in rn-dev-agent-workspace PR 52.

Suggested Fix

  • Treat a parsed null / non-object bridge result as fallback-worthy in bridgeWithFallback, and guard the tool's state.error read.
  • In the helper walk, also match forwardRef containers via type.render?.name (NavigationContainerInner) or read BaseNavigationContainer hook state, and only emit the Expo Router message when no react-navigation container was found either.

Related Issues

#951


Submitted via /rn-dev-agent:send-feedback — data sanitized automatically

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions