Skip to content

Fabric-specific crash: Refs to views with Animated.View are null, causing NullPointerException in third-party libraries #55384

@YOEL311

Description

@YOEL311

Description

Summary

This appears to be a Fabric-specific bug that causes apps to crash when using third-party libraries that access refs to views containing Animated.View wrappers.

Key points:

  • Works perfectly in Old Architecture (Bridge)
  • Crashes immediately in New Architecture (Fabric)
  • 💥 Same code, different behavior

The issue: In Fabric, refs to views wrapping Animated.View are null during initial render, causing NullPointerException when third-party libraries try to access them.

Question: Is this expected Fabric behavior, or a bug that should be fixed?

Environment

  • React Native: 0.76.0+
  • New Architecture: Enabled (newArchEnabled=true)
  • Platform: Android (issue confirmed on Fabric)

The Problem

Behavior Comparison

Aspect Old Architecture (Bridge) New Architecture (Fabric)
View mounting ✅ Synchronous. ⚠️ Asynchronous
Ref availability ✅ Immediate ❌ Delayed (can be null)
Same code behavior ✅ Works ❌ Crashes

This is a Fabric-specific regression - code that works in Bridge crashes in Fabric.

Minimal Reproduction

I've created a minimal reproduction repository:
https://github.com/YOEL311/reproduceRNNewArchBug

The Issue

import { A11yOrder, useFocusOrder } from 'react-native-a11y';
import Animated from 'react-native-reanimated';

export default function App() {
  const { a11yOrder, refs } = useFocusOrder(2);

  return (
    <A11yOrder a11yOrder={a11yOrder}>
      <View ref={refs[0]}>
        <Text>Component 1</Text>
      </View>

      {/* This crashes because refs[1] is null when A11yOrder tries to access it */}
      <View ref={refs[1]}>
        <Animated.View>
          <Text>Animated Component</Text>
        </Animated.View>
      </View>
    </A11yOrder>
  );
}

The Root Cause

Current code in react-native-a11y (A11yReader.java:88-95):

https://github.com/ArturKalach/react-native-a11y/blob/ac76ac984d97dc73cd1bbda0fc8ab2f4508ddf75/android/src/main/java/com/reactnativea11y/services/A11yReader.java#L91-L96

  @RequiresApi(api = Build.VERSION_CODES.N)
  public void setA11yOrder(@NonNull ReadableArray reactTags) {
    final int length = reactTags.size();
    if (length < 2) return;


    final Activity activity = context.getCurrentActivity();

    if (activity == null) {
      return;
    }

    activity.runOnUiThread(() -> {
      try {
        RCA11yUIManagerHelper uiHelper = new RCA11yUIManagerHelper(context);
        final ArrayList<View> views = new ArrayList<>();
        for (int i = 0; i < length; i++) {
          try {
            views.add(uiHelper.resolveView(reactTags.getInt(i)));
          } catch (IllegalViewOperationException error) {
            Log.e("ERROR", error.getMessage());
          }
        }
        for (int i = 0; i < views.size() - 1; i++) {
          final View currentView = views.get(i);
          final View nextView = views.get(i + 1);
          currentView.setNextFocusForwardId(nextView.getId());
          currentView.setAccessibilityTraversalBefore(nextView.getId());
        }
      } catch (IllegalViewOperationException error) {
        Log.e("KEYBOARD_FOCUS_ERROR", error.getMessage());
      }
    });

Why it crashes (Fabric-specific issue):

  • In Old Architecture (Bridge): ✅ Works perfectly - Views mounted synchronously, views.get(i + 1) always returns a valid View
  • In New Architecture (Fabric): ❌ Crashes - Views wrapped in Animated.View mounted asynchronously, views.get(i + 1) returns null

This only happens in Fabric - the exact same code works without issues in the old architecture.

Workaround (But is it correct?)

The library can add a null check:

for (int i = 0; i < views.size() - 1; i++) {
  final View currentView = views.get(i);
  final View nextView = views.get(i + 1);

  // ✅ This prevents the crash
  if (currentView != null && nextView != null) {
    currentView.setNextFocusForwardId(nextView.getId());
    currentView.setAccessibilityTraversalBefore(nextView.getId());
  }
}

This works, but raises questions:

This Appears to Be a Bug - But Is It Expected?

The Fabric-Specific Issue

Scenario:

const { a11yOrder, refs } = useFocusOrder(2);

<A11yOrder a11yOrder={a11yOrder}>
  <View ref={refs[0]}>...</View>

  <View ref={refs[1]}>
    <Animated.View>...</Animated.View>
  </View>
</A11yOrder>;

In Old Architecture: Both refs[0] and refs[1] are available ✅
In Fabric: refs[1] is null when accessed ❌

This looks like a bug because:

  1. Same code works in Bridge, crashes in Fabric
  2. No API changes were made
  3. No migration documentation mentions this
  4. Breaks backward compatibility

But we need clarification:

  • Is this intentional Fabric behavior?
  • Should all libraries add null checks for Fabric compatibility?
  • Or will this be fixed in Fabric?

Question 2: What's the recommended pattern?

If null checks are the recommended approach:

if (currentView != null && nextView != null) {
  // Safe to access
}

But this silently fails:

  • Accessibility ordering is skipped
  • No error is reported
  • Features break without developers knowing

Should libraries instead:

  1. Wait for mounting? (How? There's no callback)
  2. Retry with delays? (Unreliable and hacky)
  3. Log warnings? (What should the warning say?)

Question 3: Breaking change documentation?

If this is expected Fabric behavior, it's a breaking change from the old architecture.

Steps to reproduce

git clone https://github.com/YOEL311/reproduceRNNewArchBug
cd reproduceRNNewArchBug
yarn
yarn android

React Native Version

0.81.2

Affected Platforms

Runtime - Android

Areas

Fabric - The New Renderer

Output of npx @react-native-community/cli info

`
System:
  OS: macOS 26.1
  CPU: (12) arm64 Apple M3 Pro
  Memory: 148.91 MB / 18.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 22.17.1
    path: /Users/###/.nvm/versions/node/v22.17.1/bin/node
  Yarn:
    version: 1.22.22
    path: /Users/###/.nvm/versions/node/v22.17.1/bin/yarn
  npm:
    version: 10.9.2
    path: /Users/###/.nvm/versions/node/v22.17.1/bin/npm
  Watchman:
    version: 2025.05.26.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.16.2
    path: /usr/local/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 25.2
      - iOS 26.2
      - macOS 26.2
      - tvOS 26.2
      - visionOS 26.2
      - watchOS 26.2
  Android SDK: Not Found
IDEs:
  Android Studio: 2025.1 AI-251.25410.109.2511.13665796
  Xcode:
    version: 26.2/17C52
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.15
    path: /Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 19.1.1
    wanted: 19.1.1
  react:
    installed: 19.1.0
    wanted: 19.1.0
  react-native:
    installed: 0.80.2
    wanted: 0.80.2
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: Not found
  newArchEnabled: false
`

Stacktrace or Logs

          E  FATAL EXCEPTION: main (Ask Gemini)
 Process: com.test80, PID: 17622
 java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getId()' on a null object reference
     	at com.reactnativea11y.services.A11yReader.lambda$setA11yOrder$0(A11yReader.java:94)
   at com.reactnativea11y.services.A11yReader.$r8$lambda$7Pp-de0q43EZIQ89q5T3KV4D0lE(Unknown Source:0)
     at com.reactnativea11y.services.A11yReader$$ExternalSyntheticLambda1.run(D8$$SyntheticClass:0)
      at android.os.Handler.handleCallback(Handler.java:995)
       at android.os.Handler.dispatchMessage(Handler.java:103)
     at android.os.Looper.loopOnce(Looper.java:273)
       	at android.os.Looper.loop(Looper.java:363)
       at android.app.ActivityThread.main(ActivityThread.java:10060)
       	at java.lang.reflect.Method.invoke(Native Method)
      	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632)
     	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
`

MANDATORY Reproducer

https://github.com/YOEL311/reproduceRNNewArchBug

Screenshots and Videos

App crashes immediately on launch with NullPointerException when using react-native-a11y with Fabric enabled.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions