Skip to content

Android: handleBackPress throws "Could not get native view tag" on hardware back during sheet teardown (race) #718

Description

@sagnik2001

Before submitting a new issue

  • I tested using the latest version of the library.
  • I tested using a supported version of React Native.
  • I checked for existing issues that might answer my question.

Bug Summary

On Android (New Architecture / Fabric), pressing the hardware back button while a presented sheet's native view is being torn down throws Error: Could not get native view tag. It's caught by RN's BackHandler emit and surfaces as a non-fatal in Crashlytics, but the back press silently no-ops and it pollutes crash reporting.
Introduced by #580, which routes hardware back through BackHandler.addEventListener('hardwareBackPress', this.handleBackPress).

The subscription is added in onDidPresent and only removed in onDidDismiss / componentWillUnmount. There is a window where the sheet's native view is detached (e.g. the host screen is popped/unmounted by navigation) before onDidDismiss runs to remove the subscription. In that window:

isPresented and isSheetVisible are both still true, so handleBackPress does not early-return, and
findNodeHandle(this.nativeRef.current) returns null
so the get handle() getter throws:

private get handle(): number {
const nodeHandle = findNodeHandle(this.nativeRef.current);
if (nodeHandle == null || nodeHandle === -1) {
throw new Error('Could not get native view tag'); // <-- thrown from BackHandler callback
}
return nodeHandle;
}

private handleBackPress(): boolean {
if (!this.isPresented || !this.isSheetVisible) return false;
TrueSheetModule?.handleBackPress(this.handle); // <-- reads throwing getter
return this.props.onBackPress?.() ?? true;
}

Affected Platforms

  • iOS
  • Android
  • Web
  • Other

Library Version

3.10.0

Environment Info

React Native: 0.83.1, New Architecture (Fabric) enabled
Platform: Android only
Repro frequency increases on low-end devices (seen on a Redmi 9A / M2006C3MII, Helio G25)

Steps to Reproduce

It's a timing race, so it's flaky by hand (easier on a slow device / CPU-throttled emulator):

  1. Present a sheet hosted in a navigation screen.
  2. From inside the sheet, trigger navigation that unmounts the host screen without dismissing the sheet first.
  3. Spam the hardware back button during the transition.

Repro

https://github.com/sagnik2001/rn-true-sheet-backpress-repro

Additional Context

Resolve the node handle directly in handleBackPress and bail out cleanly if it's unavailable, instead of relying on the throwing getter:

private handleBackPress(): boolean {
if (!this.isPresented || !this.isSheetVisible) return false;

  • TrueSheetModule?.handleBackPress(this.handle);
  • // The native view can be detached (e.g. host screen unmounted by navigation)
  • // before onDidDismiss removes this subscription. In that window the tag is
  • // gone — treat back press as a no-op instead of throwing.
  • const nodeHandle = findNodeHandle(this.nativeRef.current);
  • if (nodeHandle == null || nodeHandle === -1) return false;
  • TrueSheetModule?.handleBackPress(nodeHandle);
    return this.props.onBackPress?.() ?? true;
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrepro providedGood! Repro is provided

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions