Skip to content

Fix a startup crash when an Image is created before Fresco is initialized - #59701

Open
tomekzaw wants to merge 2 commits into
react:mainfrom
tomekzaw:fix-fresco-init-race
Open

tomekzaw wants to merge 2 commits into
react:mainfrom
tomekzaw:fix-fresco-init-race

Conversation

@tomekzaw

Copy link
Copy Markdown
Contributor

Summary:

In bridgeless mode, eager modules are created on the native modules thread while the JS bundle loads (ReactHostImpl). FrescoModule is one of them, and it initializes Fresco. If the first render preallocates an Image before that has finished, ReactImageManager.createViewInstance calls Fresco.newDraweeControllerBuilder() too early and the app crashes on startup:

java.lang.NullPointerException
  at com.facebook.common.internal.Preconditions.checkNotNull(Preconditions.java:213)
  at com.facebook.drawee.backends.pipeline.Fresco.newDraweeControllerBuilder(Fresco.java:139)
  at com.facebook.react.views.image.ReactImageManager.createViewInstance(ReactImageManager.kt:95)
  at com.facebook.react.fabric.mounting.SurfaceMountingManager.preallocateView(SurfaceMountingManager.kt:1123)

When FrescoModule hasn't finished initializing Fresco, createViewInstance now gets the module first. TurboModuleManager then either waits for the other thread to finish creating it or creates it on the spot. This uses FrescoModule.hasBeenInitialized() rather than Fresco.hasBeenInitialized(), because Fresco sets its flag when initialization starts, not when it ends. Once Fresco is initialized, the only extra work is reading that flag.

Changelog:

[ANDROID] [FIXED] - Fix a startup crash when an Image is created before Fresco finishes initializing

Test Plan:

Release RNTester (./gradlew :packages:rn-tester:android:app:assembleRelease -PreactNativeArchitectures=arm64-v8a), cold-started from the launcher repeatedly on a Galaxy A16 (Android 16). A run counts as a crash when the log has the stack trace above.

Feature flags main This PR
Default 5 of 40 cold starts crashed 0 of 40
Experimental release level 13 of 40 0 of 40

After the change, the Image examples load their network images as before.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 30, 2026
@tomekzaw
tomekzaw marked this pull request as ready for review October 31, 2026 08:23
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 31, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
// FrescoModule initializes Fresco on the native modules thread while the JS bundle loads, so
// the first Image can be created before that finishes. Getting the module waits for it.
// Fresco.hasBeenInitialized() doesn't help here: it turns true when initialization starts.
context.reactApplicationContext.getNativeModule(FrescoModule::class.java)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fresco initialization can be pretty costly, and the createViewInstance method is called on the main thread. Since the builder isn't called until the image mounts and has dimensions, could we instead make the constructor argument a Provider<T> for a drawee controller builder?

This branch has not been deployed

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

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants