Bug: iOS Error: Unknown std::runtime_error when using react-native-skia
What's happening?
Firstly, this project is awesome!
When @shopify/react-native-skia is added as a dependency and pods are installed, error messages from Swift/C++ native code are no longer propagated correctly to JavaScript. Instead of showing the actual error message, all errors show as "Error: Unknown std::runtime_error error."
I noticed this in my private Expo App (using Expo 53/React Native 0.79.5 initially and persisted in Expo 54/React Native 0.81.4) when none of my error contexts from my own Nitro Module usingRuntimeError.error(withMessage: [custom error message] were propagating to my JS code.
I have easily been able to reproduce this error by adding react-native-skia to the example app of this repo.
This issue was previously mentioned in #382, but that issue was closed. The problem still persists on the latest main branch. Without react-native-skia installed, all tests pass correctly and error messages propagate as expected.
It seems like there might be a conflict in how error handling works when multiple native modules using C++/JSI are present. The error messages are being stripped somewhere in the exception propagation chain when Skia is loaded.
Reproduceable Code
Relevant log output
❌ Test "funcThatThrows() throws" failed!
Expected: "TestObjectCpp.funcThatThrows(...):"
Got: "Error: `TestObjectCpp.funcThatThrows(...)` threw an unknown std::runtime_error error."
❌ Test "funcThatThrowsBeforePromise() throws" failed!
Expected: "TestObjectCpp.funcThatThrowsBeforePromise(...):"
Got: "Error: `TestObjectCpp.funcThatThrowsBeforePromise(...)` threw an unknown std::runtime_error
error."
❌ Test "set someVariant to false" failed!
Expected: "Error: TestObjectCpp.someVariant: Cannot convert "false" to any type in
variant<std::string, double>!"
Got: "Error: `TestObjectCpp.someVariant` threw an unknown std::runtime_error error."
❌ Test "promiseThrows() throws" failed!
Expected: "Error: Promise throws :)"
Got: "Error: Unknown std::runtime_error error."
[... 9 total test failures with same pattern]
Device
iPhone 16 - iOS 18.3.1
Nitro Modules Version
0.29.8
Nitrogen Version
0.29.8
Can you reproduce this issue in the Nitro Example app here?
Yes, I can reproduce the same issue in the Example app here
Additional information
- [x] I am using Expo
- [x] I am using nitrogen
- [x] I have read and followed the Troubleshooting Guide.
- [x] I created a reproduction PR to reproduce this issue here in the nitro repo. (See Contributing for more information)
- [x] I searched for similar issues in this repository and found none.
That is super weird. The issue you mentioned (#382) was closed because we fixed the actual problem in upstream react-native core.
The issue was, that -fexceptions was not enabled in react-native core, causing it to also not be enabled in Nitro Modules since those are imported by react-native core, and not always built by it (header vs .cpp file).
Now; react-native-skia really shouldn't affect this anyhow. @wcandillon any ideas?
- Can you confirm that adding react-native-skia does not change any dependencies (like react-native core) anyhow?
- We probably need to check if react-native-skia has any headers or namespaces that conflict with the Nitro ones. @wcandillon I don't think you use the early prototype of Nitro I sent you back in the day for Skia, right? Only for WebGPU?
- Can Skia throw exceptions fine? In Skia code (e.g. some
MakeImage...func) can we throw a std::runtime_error and have the message be propagated to JS? - If not, we probably need to enable
-fexceptionsfor react-native-skia
Which platforms did you test btw? I see iOS/Swift, but did you also test Android?
@mrousavy Thanks for cc'ing me on this.
My assumption is that -fexceptions is enabled by default on newer React Native versions (we had to explicitly enable it on Android for older RN versions). But this assumption might be wrong and this should be revisited.
I am not knowledgeable yet on the best practices to throw errors in JSI. Where would be a good place to look at? I'd be happy to align there.
We do not use any margelo/nitro namespaces in Skia or Skia Graphite.
I am not knowledgeable yet on the best practices to throw errors in JSI
Just throw - that's what I do in Nitro too. I just wrap them for better error messages
My assumption is that -fexceptions is enabled by default on newer React Native versions
I think so too, that's why I found this issue to be so confusing.
I'm guessing if this issue can be reproduced here (#920), it's not Expo related, and it's also not an older react-native version.
I just wonder; do you throw any errors in react-native-skia? If yes, does that work fine with error messages and all?
Last time I tried it I was happy with the behavior of the error throwing. There is two kinds of errors: Errors which are thrown directly from a JSI call (on JS or worklet thread) Errors which are from C++ rendering (scene graph)
But could definitely check it again and consolidate things if needed.
I think I'm running into the same issue. The errors work in the example project of @kingstinct/react-native-healthkit (which uses nitro) but not in another project using both react-native-skia and @kingstinct/react-native-healthkit as dependencies (both projects on Expo 54 with Expo-aligned dependencies).
is this on iOS? Android? both? I think there is a legitimate concern here, I'm just still confused about this topic.
is this on iOS? Android? both? I think there is a legitimate concern here, I'm just still confused about this topic.
In this case iOS only.
I just reproduced the issue by adding react-native-skia to the example app in react-native-healthkit.
Are there any news on that one? I face the exact same issue, all my exceptions on iOS turn into [Error: Unknown std::runtime_error error.] making it impossible to tell what fails.
Could it be related to this one? https://issues.skia.org/issues/316196498 It is from 2023 though... hard to believe but not impossible.
wtf, it is indeed that issue... I built skia from sources and copied over the libskia.a and now I get this
instead of
closed via https://github.com/Shopify/react-native-skia/pull/3595 - thanks @wcandillon