Hermes: TypeError: Cannot determine default value of object in 0.4.2-rc1

Created on 2 Apr 2020  路  8Comments  路  Source: facebook/hermes

I'm getting this error after updating to 0.4.2-rc1.

TypeError: Cannot determine default value of object
  at Number(app:///native)
  at sanitizeValue(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/core/InternalAnimatedValue.js:8:7)
  at constructor(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/core/InternalAnimatedValue.js:35:35)
  at valueForConstant(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/core/InternalAnimatedValue.js:30:42)
  at nodify(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/core/AnimatedBlock.js:45:29)
  at adapt(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/core/AnimatedBlock.js:51:7)
  at createAnimatedCond(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/core/AnimatedCond.js:54:5)
  at proc$argument_0(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/derived/onChange.js:6:5)
  at apply(app:///native)
  at createAnimatedFunction(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/core/AnimatedFunction.js:41:18)
  at <global>(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/derived/onChange.js:4:22)
  at loadModuleImplementation(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:321:5)
  at guardedLoadModule(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:210:12)
  at metroRequire(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:128:7)
  at <global>(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/derived/index.js:9:1)
  at loadModuleImplementation(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:321:5)
  at guardedLoadModule(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:210:12)
  at metroRequire(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:128:7)
  at <global>(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/Animated.js:8:1)
  at loadModuleImplementation(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:321:5)
  at guardedLoadModule(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:210:12)
  at metroRequire(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:128:7)
  at <global>(/Users/janic/Developer/th3rdwave/packages/ui/src/components/Animated/Animated.tsx:3:1)
  at loadModuleImplementation(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:321:5)
  at guardedLoadModule(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:210:12)
  at metroRequire(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:128:7)
  at <global>(/Users/janic/Developer/th3rdwave/packages/ui/src/components/Animated/index.ts:1:1)
  at loadModuleImplementation(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:321:5)
  at guardedLoadModule(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:210:12)
  at metroRequire(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:128:7)
  at <global>(/Users/janic/Developer/th3rdwave/packages/ui/src/components/index.ts:1:1)
  at loadModuleImplementation(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:321:5)
  at guardedLoadModule(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:210:12)
  at metroRequire(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:128:7)
  at <global>(/Users/janic/Developer/th3rdwave/packages/ui/src/index.ts:2:1)
  at loadModuleImplementation(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:321:5)
  at guardedLoadModule(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:210:12)
  at metroRequire(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:128:7)
  at <global>(src/components/App.tsx:16:1)
  at loadModuleImplementation(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:321:5)
  at guardedLoadModule(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:210:12)
  at metroRequire(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:128:7)
  at <global>(index.js:41:13)
  at loadModuleImplementation(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:321:5)
  at guardedLoadModule(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:201:21)
  at metroRequire(/Users/janic/Developer/th3rdwave/node_modules/metro/src/lib/polyfills/require.js:128:7)
  at global(index.android.bundle:222:16)

It happens on app launch. Seem to be triggered by requiring react-native-reanimated.

I cannot reproduce the issue in the simulator (release) and it doesn't seem to happen in all versions of android. I noticed it in the play store pre-launch report. Here's the breakdown of android versions and if the crash happened.

image

Using RN master @ fb9a7be2bdba0ccc8b10806a247f8989dc343e04

need more info

Most helpful comment

@janicduplessis and others:

With the recent release of hermes 0.5.1 and 0.5.2-rc1 (Proxy opt-in), we are also now publishing unstripped libraries in the github releases which at long last give us the ability to symbolicate native crashes.

If you seen native crashes with Proxy in the past, please try to repro with RN 0.63 and Hermes 0.5.2-rc1. If you get a crash, please post it. You can also try to symbolicate it yourself using the instructions at https://github.com/facebook/hermes/blob/master/doc/ReactNativeIntegration.md#reporting-native-crashes

Thanks!

All 8 comments

Thanks for the bug report!

As you can see from the stack trace, this comes from this JS code: https://github.com/software-mansion/react-native-reanimated/blob/master/src/core/InternalAnimatedValue.js#L8

The error message is emitted when the argument passed to Number() is not convertible to a primitive. I can think of a couple ways to cause this to happen offhand, by passing an object which has no toString or valueOf property which can be called:

>> Number(Object.create(null))
TypeError: Cannot determine default value of object
    at Number (native)
    at global (JavaScript:1:7)
>> Number(new Proxy({}, {get() {}}))
TypeError: Cannot determine default value of object
    at Number (native)
    at global (JavaScript:1:7)

JSC also throws an exception with these inputs, but it's different: "TypeError: No default value". Google does find some instances of this error in RN apps, but not related to reanimated as far as I can tell.

I do see that there is code in reanimated which is conditional on the existence of Proxy: https://github.com/software-mansion/react-native-reanimated/blob/2a48891a6c626bc336ba64ca54e785fbdac501f4/src/core/AnimatedEvent.js#L70
I don't know much about reanimated, but it certainly plausible that if a function with the right (wrong?) properties were wrapped using that code and somehow got passed to InternalAnimatedValue, it would result in a crash like this.

If you can reproduce this in the play store, there's a couple things to try:

  1. try [email protected] and see if it still happens.
  2. Modify the code to wrap a try/catch around the statement which is throwing the exception, and add some logging to see what value is.

More generally, I would approach this as a bug in JS code, and determine what is causing the invalid input, or come up with a repro case which demonstrates that JS is not behaving according to spec for some particular code or input.

I don't have a theory as to why this behaves differently on different android versions.

@mhorowitz I'm really confused about this one. I can confirm that 0.4.1 works fine. The best log I'm able to do around value is typeof which is "object". Any other log triggers the error again since it tries to convert it to a string. I also tried for ... in to log keys but now I'm getting a very weird crash.

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Sony/G8441/G8441:8.0.0/47.1.A.12.205/2573353275:user/release-keys'
Revision: '0'
ABI: 'arm64'
pid: 17775, tid: 17890, name: mqt_js  >>> com.th3rdwavemerchant <<<
signal 7 (SIGBUS), code 1 (BUS_ADRALN), fault addr 0x40ffff007b2c4361
    x0   0000007b2cbdcab0  x1   0000007b2e29c000  x2   0000000000000002  x3   0000007b2d640128
    x4   0000007b2d63ff70  x5   0000007b2d63ff38  x6   0000007b2d63fea0  x7   0000007b2d63fea0
    x8   40ffff007b2c4361  x9   0000000000000001  x10  0000000000000004  x11  0000000000000004
    x12  0000007b2d63fea0  x13  0000000000000002  x14  0000007b2c400000  x15  0000007b2d640168
    x16  0000007b2dfab620  x17  0000007b4c71c970  x18  000000007ff00000  x19  0000007b2e29c000
    x20  0000000000000002  x21  0000007b2d642588  x22  0000007b2d640170  x23  0000007b2d63ff20
    x24  0000007b2d640198  x25  0000007b2d640188  x26  fff8800000000000  x27  0000007b2d63fea0
    x28  0000000000000004  x29  0000007b2d63fde0  x30  0000007b2de155b4
    sp   0000007b2d63fc80  pc   40ffff007b2c4361  pstate 0000000040000000
backtrace:
    #00 pc 40ffff007b2c4361  <unknown>
    #01 pc 00000000000495b0  /data/data/com.th3rdwavemerchant/lib-0/libhermes.so
    #02 pc 00000000000505b0  /data/data/com.th3rdwavemerchant/lib-0/libhermes.so
    #03 pc 00000000000422dc  /data/data/com.th3rdwavemerchant/lib-0/libhermes.so
    #04 pc 0000000000032f14  /data/data/com.th3rdwavemerchant/lib-0/libhermes.so
    #05 pc 0000000000031c98  /data/data/com.th3rdwavemerchant/lib-0/libhermes.so
    #06 pc 00000000000a1ff4  /data/data/com.th3rdwavemerchant/lib-0/libhermes.so
    #07 pc 0000000000032b14  /data/data/com.th3rdwavemerchant/lib-0/libhermes.so
    #08 pc 0000000000041e44  /data/data/com.th3rdwavemerchant/lib-0/libhermes.so
    #09 pc 0000000000066d08  /data/data/com.th3rdwavemerchant/lib-0/libhermes.so
    #10 pc 0000000000022420  /data/data/com.th3rdwavemerchant/lib-0/libhermes.so
    #11 pc 00000000000226a4  /data/data/com.th3rdwavemerchant/lib-0/libhermes.so
    #12 pc 00000000000245c8  /data/data/com.th3rdwavemerchant/lib-0/libhermes-executor-release.so
    #13 pc 00000000000a1478  /data/data/com.th3rdwavemerchant/lib-0/libreactnativejni.so
    #14 pc 00000000000a2e74  /data/data/com.th3rdwavemerchant/lib-0/libreactnativejni.so
    #15 pc 0000000000069408  /data/data/com.th3rdwavemerchant/lib-0/libreactnativejni.so
    #16 pc 000000000005a25c  /data/data/com.th3rdwavemerchant/lib-0/libreactnativejni.so
    #17 pc 000000000005a1d8  /data/data/com.th3rdwavemerchant/lib-0/libreactnativejni.so
    #18 pc 00000000000bb74c  /data/app/com.th3rdwavemerchant-YWsKaUYbDczCMWvoNzoM0A==/oat/arm64/base.odex (offset 0x90000)

Sadly it isn't symbolicated so not sure what to do about it.

I've also gotten this on Android 5 only...

TypeError: Object is not a function
  at constructor(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/core/AnimatedParam.js:12:10)
  at createAnimatedParam(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/core/AnimatedParam.js:84:10)
  at createAnimatedFunction(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/core/AnimatedFunction.js:38:17)
  at <global>(/Users/janic/Developer/th3rdwave/node_modules/react-native-reanimated/src/derived/onChange.js:4:22)

I find the different behavior on different devices / android versions very odd. Certain work perfectly fine. This is really hard to test for me since I can't repro on a local device.

Also Number(new Proxy({}, {get(target, name) { return target[name]; }})) should work if the proxy returns something in the get. Tested this in safari.

I also played with the code in reanimated a bit. The interesting parts I found is

const proxyHandler = {
      get: function(target, name) {
        if (name === '__isProxy') { // <- Returns true for __isProxy
          return true;
        }
        if (!target[name] && name !== '__val') {
          target[name] = new Proxy({}, proxyHandler);
        }
        return target[name];
      },
      [...]
    };

Then https://github.com/software-mansion/react-native-reanimated/blob/2a48891a6c626bc336ba64ca54e785fbdac501f4/src/core/AnimatedBlock.js#L36 is in the code path that leads to where the crash happens. It should prevent proxies from reaching the Number(...) call in sanitizeValue but looks like it doesn't. I'm also able to trigger a lot of errors by logging this proxy object but not Cannot determine default value of object.

var proxyHandler = {
      get: function (target, name) {
        if (name === '__isProxy') {
          return true;
        }
        if (!target[name] && name !== '__val') {
          target[name] = new Proxy({}, proxyHandler);
        }
        return target[name];
      },
      set: function (target, prop, value) {
        if (prop === '__val') {
          target[prop] = value;
          return true;
        }
        return false;
      },
    };
    Number(new Proxy({}, proxyHandler)); // <- TypeError: Could not get callable method from object

Will report back if I find anything else when I get more time to investigate.

@janicduplessis thanks for digging in. I agree, this is all very strange. The native crash should definitely not happen. My general suggestion would be to rebuild hermes with symbols, but unfortunately, I'm not sure how to tell you to do that with cmake.

I don't envy you trying to debug this without having a local repro. We get those from time to time and they are very hard to debug.

I think my best thought right now is to add instrumentation down the call path to try to trace where the value is being created. At least this is happening at initialization, which should be more or less deterministic.

Thanks for your efforts!

I'm getting a similar but equally opaque "Cannot determine default value of object" issue that comes from this line: https://github.com/software-mansion/react-native-reanimated/blob/master/src/core/AnimatedOperator.js#L76

I wish I had more information but the stack trace is useless. Same library though..

@arlyon Someone else reported that the version of the @babel/plugin-transform-classes plugin might be relevant here: https://github.com/facebook/hermes/issues/33#issuecomment-641917567

Are you using this plugin, and which version of it are you using? Does changing it affect the behavior?

If you were willing to take the time to post a standalone JS file which fails, or even app which we could compile to reproduce the failure, then we could probably get to the bottom of this. Unfortunately, we don't yet have enough information to understand this bug.

Hi, I am running 7.9.5 and will try out 7.8.x, but the issue appears intermittently so some more testing will be needed to confirm. Thanks for the tip.

@janicduplessis and others:

With the recent release of hermes 0.5.1 and 0.5.2-rc1 (Proxy opt-in), we are also now publishing unstripped libraries in the github releases which at long last give us the ability to symbolicate native crashes.

If you seen native crashes with Proxy in the past, please try to repro with RN 0.63 and Hermes 0.5.2-rc1. If you get a crash, please post it. You can also try to symbolicate it yourself using the instructions at https://github.com/facebook/hermes/blob/master/doc/ReactNativeIntegration.md#reporting-native-crashes

Thanks!

@mhorowitz I just tested 0.5.2-rc1 and the crash does not seem to happen anymore. I will keep further testing and report back if I get any crash.

Was this page helpful?
0 / 5 - 0 ratings