Skip to content

🚨 Regression in 5.9.0: NoClassDefFoundError: SafeAreaContextModule crashes app on launch (Paper / Old Architecture) #754

Description

@Yahoel

Summary

react-native-safe-area-context@5.9.0 introduces a regression that causes immediate crash on app launch with NoClassDefFoundError for projects using the Paper (Old Architecture) build. The root cause is a sourceSets configuration change in android/build.gradle that silently strips NativeSafeAreaContextSpec.java from the dex output.

This is a critical regression — any Paper-architecture project that resolves to 5.9.0 will crash on launch, with no compile-time warning. Because the failure is at runtime (not compile time), the only signal is the crash report after users open the app.

Version Comparison

Version sourceSets.main config Result
5.8.0 / 5.8.1 java { srcDirs += ["src/paper/java"] } ✅ NativeSafeAreaContextSpec.java compiled
5.9.0 kotlin.directories.add("src/paper/java") ❌ NativeSafeAreaContextSpec.java stripped

The Bug

In 5.8.1 and earlier, the Paper branch was correctly registered as a Java source set:

sourceSets.main {
    java {
        if (isNewArchitectureEnabled()) {
            srcDirs += ["src/fabric/java", "${project.buildDir}/generated/source/codegen/java"]
        } else {
            srcDirs += ["src/paper/java"]  // both .kt and .java files processed
        }
    }
}

In 5.9.0, this was changed to only register the Kotlin source set:

sourceSets.main {
    if (isNewArchitectureEnabled()) {
        java.directories.add("${project.buildDir}/generated/source/codegen/java")
        kotlin.directories.add("src/fabric/java")
    } else {
        kotlin.directories.add("src/paper/java")  // ← BUG: only Kotlin source set
    }
}

The inline comment says "contains both java and kotlin files", but the directory is only added to kotlin.directories. With newer Kotlin Gradle Plugin versions, .java files placed under kotlin.directories are silently skipped — they are not compiled by either javac or kotlanc.

Why It Crashes

The src/paper/java/ directory contains:

  • InsetsChangeEvent.kt ✅ compiled
  • UIManagerHelperCompat.kt ✅ compiled
  • NativeSafeAreaContextSpec.java ❌ skipped

SafeAreaContextModule (in src/main/java/) extends NativeSafeAreaContextSpec. At runtime, ART tries to load SafeAreaContextModule, fails to resolve its superclass NativeSafeAreaContextSpec (missing from dex), and throws:

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/th3rdwave/safeareacontext/SafeAreaContextModule;

Reproduction

I verified this by extracting and comparing the dex files from two production AABs built from identical source code (only the version number changed between builds):

0.9.151 AAB (built with 5.8.x) — works:

$ dexdump classes10.dex | grep "NativeSafeAreaContextSpec"
  Class descriptor  : 'Lcom/th3rdwave/safeareacontext/NativeSafeAreaContextSpec;'  ✅
  Superclass        : 'Lcom/facebook/react/bridge/ReactContextBaseJavaModule;'

0.9.174 AAB (built with 5.9.0) — crashes on launch:

$ for f in base/dex/*.dex; do
    dexdump "$f" | grep "Class descriptor.*NativeSafeAreaContextSpec"
done
# (no class definition found across all 13 dex files)  ❌

The class is still referenced (as Superclass: 'Lcom/th3rdwave/safeareacontext/NativeSafeAreaContextSpec;' and in invoke-direct calls inside SafeAreaContextModule), but its definition is missing from every dex file.

Suggested Fix

Add java.directories.add("src/paper/java") alongside the existing kotlin.directories.add(...):

sourceSets.main {
    if (isNewArchitectureEnabled()) {
        java.directories.add("${project.buildDir}/generated/source/codegen/java")
        kotlin.directories.add("src/fabric/java")
    } else {
        java.directories.add("src/paper/java")        // ← add this line
        kotlin.directories.add("src/paper/java")
    }
}

This mirrors the pattern already used in the New Architecture branch above (which correctly registers both java.directories and kotlin.directories).

Environment

  • react-native-safe-area-context: 5.9.0
  • React Native: 0.81.5
  • Android Gradle Plugin: 8.11.0
  • Gradle: 8.14.3
  • Build image: EAS ubuntu-22.04-jdk-17-ndk-r26b
  • newArchEnabled=false
  • Build profile: production release AAB

Workaround

For anyone hitting this in the meantime, here is a patch-package patch. Save as patches/react-native-safe-area-context+5.9.0.patch and ensure patch-package runs in your postinstall / prepare hook:

--- a/node_modules/react-native-safe-area-context/android/build.gradle
+++ b/node_modules/react-native-safe-area-context/android/build.gradle
@@ -102,7 +102,8 @@
             kotlin.directories.add("src/fabric/java") // contains only kotlin files
         } else {
-            kotlin.directories.add("src/paper/java") // contains both java and kotlin files
+            java.directories.add("src/paper/java")
+            kotlin.directories.add("src/paper/java")
         }

Impact

The timing of this release (5.9.0 published on 2026-08-17) coincided with EAS builds that resolved to the new version via caret ranges, silently breaking production apps that were working hours earlier. A patch release (5.9.1) with this fix would be greatly appreciated.

Happy to open a PR if that helps — just let me know.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions