react-native: Crash: JS Functions are not convertible to dynamic

Application crashes with the following stack trace:

Fatal Exception: com.facebook.jni.CppException: JS Functions are not convertible to dynamic

no stack
       at com.facebook.react.bridge.queue.NativeRunnable.run(NativeRunnable.java)
       at android.os.Handler.handleCallback(Handler.java:873)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:29)
       at android.os.Looper.loop(Looper.java:214)
       at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:232)
       at java.lang.Thread.run(Thread.java:764)

React Native version:

System:
    OS: macOS Mojave 10.14.6
    CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
    Memory: 29.94 MB / 32.00 GB
    Shell: 5.0.7 - /usr/local/bin/bash
  Binaries:
    Node: 10.16.0 - /usr/local/bin/node
    Yarn: 1.17.3 - /usr/local/bin/yarn
    npm: 6.12.0 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
    Android SDK:
      API Levels: 27, 28, 29
      Build Tools: 28.0.3, 29.0.0, 29.0.2
      System Images: android-22 | Google APIs Intel x86 Atom, android-23 | Google APIs Intel x86 Atom, android-26 | Android TV Intel x86 Atom, android-28 | Google APIs Intel x86 Atom
      Android NDK: 20.0.5594570
  IDEs:
    Android Studio: 3.5 AI-191.8026.42.35.5791312
    Xcode: 11.2.1/11B53 - /usr/bin/xcodebuild
  npmPackages:
    react: 16.9 => 16.9.0
    react-native: 0.61.3 => 0.61.3
  npmGlobalPackages:
    react-native-cli: 2.0.1

Steps To Reproduce

Can’t reproduce it reliably, I’ve received tens of crashes on Crashlytics though.

Describe what you expected to happen:

Not a crash.

Snack, code example, screenshot, or link to a repository:

This is the crash:

Fatal Exception: com.facebook.jni.CppException: JS Functions are not convertible to dynamic

no stack
       at com.facebook.react.bridge.queue.NativeRunnable.run(NativeRunnable.java)
       at android.os.Handler.handleCallback(Handler.java:873)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:29)
       at android.os.Looper.loop(Looper.java:214)
       at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:232)
       at java.lang.Thread.run(Thread.java:764)

FTR, this issue seems to be similar to https://github.com/facebook/react-native/issues/25784 but there is no 3 callback method involved as far as I can tell.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 9
  • Comments: 37 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Not stale. There is a PR open, we have tested the fix will millions of installs. I don’t know why ese to do to get the change in 😦

I’ll repost my comment from #25784: This crash has been happening over the last 2-3 months and I’m on RN 0.61.X as well. Honestly gave up on it and decided to suck it up. Sucks for the users though.

https://user-images.githubusercontent.com/15217227/64571125-317fc600-d3a6-11e9-8962-851e2dd9a151.png

We ended up finding out where the error originated, in our case. It was an Axios error instance (see https://github.com/axios/axios/blob/b3be36585884ba1e237fdd0eacf55f678aefc396/lib/core/AxiosError.js) that was being thrown as an exception. These instances contain several function objects - and for some reason, React Native on Android is unable to serialize them between threads. The JSC engine even seems to go haywire, after reporting the error cited in this issue. We modified our code to create a much simpler exception object out of an Axios error instance and throw that one instead, and this solved the issue for us.

Does anybody have any idea where to even start in triaging this crash? We pushed a very minor codepush update and are now seeing this crash all the time. Looking at the diff there doesn’t appear to be anything that would create this crash, it’s all vanilla javascript. Any help would be greatly appreciated!

No update, we continue running with a patched version, which is very annoying on Android… oh well.

We ran into the same issue as @vthorsteinsson and determined it was also due to an Axios error instance which contains functions! In case it’s useful, I included a snippet of the function we wrote to recursively clean up objects with functions inside them, mapping them to strings.

type RecursiveMapFunctionToString<T> =
  T extends Function
    ? string
    : T extends object
    ? { [K in keyof T]: RecursiveMapFunctionToString<T[K]> }
    : T

/**
 * Takes an object and returns a new object with functions mapped to strings.
 * This is required because React Native crashes when trying to serialize functions
 * (see https://github.com/facebook/react-native/issues/27203#issuecomment-1836330480)
 */
export function cleanFieldOrObject<T>(value: T): RecursiveMapFunctionToString<T>
export function cleanFieldOrObject<T>(
  value: T
): string | Record<string, unknown> | T {
  if (typeof value === 'function') {
    return value.toString()
  }
  if (typeof value === 'object' && value != null) {
    return Object.keys(value).reduce((acc, key) => {
      acc[key] = cleanFieldOrObject(value[key as keyof typeof value])
      return acc
    }, {} as Record<string, unknown>)
  }
  return value
}

Still i am facing this issue on “react-native”: “0.66.4” ? Any help on this?

Here is my package list {

“private”: true, “scripts”: { “android”: “react-native run-android”, “ios”: “react-native run-ios”, “start”: “react-native start”, “test”: “jest”, “lint”: “eslint .”, “androidBundleDebug”: “react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/”, “androidBundleRelease”: “react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/” }, “dependencies”: { “@firebase/storage”: “^0.6.1”, “@invertase/react-native-apple-authentication”: “^2.1.2”, “@notifee/react-native”: “^4.1.0”, “@ptomasroos/react-native-multi-slider”: “https://github.com/me-usman-khalid/react-native-multi-slider.git”, “@react-native-async-storage/async-storage”: “^1.15.5”, “@react-native-clipboard/clipboard”: “^1.8.4”, “@react-native-community/cookies”: “^5.0.1”, “@react-native-community/masked-view”: “^0.1.11”, “@react-native-community/netinfo”: “^8.0.0”, “@react-native-community/push-notification-ios”: “^1.10.1”, “@react-native-firebase/analytics”: “12.8.0”, “@react-native-firebase/app”: “12.8.0”, “@react-native-firebase/auth”: “12.8.0”, “@react-native-firebase/crashlytics”: “12.8.0”, “@react-native-firebase/dynamic-links”: “12.8.0”, “@react-native-firebase/installations”: “12.8.0”, “@react-native-firebase/messaging”: “12.8.0”, “@react-native-firebase/remote-config”: “12.8.0”, “@react-native-firebase/storage”: “12.8.0”, “@react-native-google-signin/google-signin”: “^6.0.1”, “@react-navigation/material-bottom-tabs”: “^6.0.9”, “@react-navigation/material-top-tabs”: “^6.0.6”, “@react-navigation/native”: “^6.0.6”, “@react-navigation/stack”: “^6.0.11”, “@talkjs/react-native”: “^0.1.0”, “ansi-regex”: “^5.0.1”, “apple-signin-auth”: “^1.5.1”, “axios”: “^0.25.0”, “convert-string”: “^0.1.0”, “firebase-dynamic-links”: “^1.1.0”, “mixpanel-react-native”: “^1.4.1”, “moment”: “^2.29.2”, “nth-check”: “^2.0.1”, “prop-types”: “^15.7.2”, “react”: “17.0.2”, “react-native”: “0.66.4”, “react-native-apple-authentication”: “^2.0.0”, “react-native-background-timer”: “^2.4.1”, “react-native-ble-manager”: “^7.5.0”, “react-native-config”: “^1.4.5”, “react-native-device-info”: “^8.3.2”, “react-native-dropdown-picker”: “^5.2.3”, “react-native-error-boundary”: “^1.1.12”, “react-native-fbsdk-next”: “^7.3.3”, “react-native-geolocation-service”: “^5.3.0-beta.4”, “react-native-gesture-handler”: “^1.10.3”, “react-native-image-picker”: “^4.0.6”, “react-native-image-viewing”: “^0.2.1”, “react-native-inappbrowser-reborn”: “^3.6.3”, “react-native-linear-gradient”: “^2.5.6”, “react-native-localize”: “^2.1.5”, “react-native-maps”: “^0.30.1”, “react-native-markdown-display”: “^7.0.0-alpha.2”, “react-native-markdown-package”: “^1.8.1”, “react-native-modal”: “^12.0.2”, “react-native-pager-view”: “^5.4.9”, “react-native-paper”: “^4.9.1”, “react-native-push-notification”: “^8.1.0”, “react-native-reanimated”: “^2.3.1”, “react-native-safe-area-context”: “^3.3.2”, “react-native-screens”: “^3.10.1”, “react-native-settings”: “^0.2.3”, “react-native-size-matters”: “^0.4.0”, “react-native-spinkit”: “^1.5.1”, “react-native-splash-screen”: “^3.2.0”, “react-native-store-version”: “^1.3.2”, “react-native-svg”: “^12.1.1”, “react-native-tab-view”: “^3.1.1”, “react-native-typewriter”: “^0.7.0”, “react-native-vector-icons”: “^8.1.0”, “react-native-video”: “^5.1.1”, “react-native-video-controls”: “^2.8.1”, “react-native-view-shot”: “^3.1.2”, “react-native-webview”: “^11.13.0”, “react-navigation-tabs”: “^2.11.1”, “react-redux”: “^7.2.4”, “redux”: “^4.1.0”, “redux-saga”: “^1.1.3”, “rn-placeholder”: “^3.0.3”, “underscore”: “^1.13.1”, “utf8”: “^3.0.0” }, “resolutions”: { “ansi-regex”: “^5.0.1”, “underscore”: “^1.13.1”, “nth-check”: “^2.0.1” }, “devDependencies”: { “@babel/core”: “^7.14.3”, “@babel/runtime”: “^7.14.0”, “@react-native-community/eslint-config”: “^2.0.0”, “babel-jest”: “^27.0.2”, “eslint”: “^7.32.0”, “eslint-config-airbnb”: “^19.0.1”, “eslint-plugin-import”: “^2.25.3”, “eslint-plugin-jsx-a11y”: “^6.5.1”, “eslint-plugin-react”: “^7.27.1”, “eslint-plugin-react-hooks”: “^4.3.0”, “jest”: “^27.0.4”, “metro-react-native-babel-preset”: “^0.66.2”, “react-native-codegen”: “^0.0.7”, “react-native-flipper”: “^0.138.0”, “react-test-renderer”: “17.0.2”, “redux-flipper”: “^2.0.1” }, “jest”: { “preset”: “react-native” } }