oblador / react-native-vector-icons

Customizable Icons for React Native with support for image source and full styling.
https://oblador.github.io/react-native-vector-icons/
MIT License
17.31k stars 2.12k forks source link

iOS + Hermes, Error: Font failed to load (generatorResume) #1465

Closed tapz closed 11 months ago

tapz commented 1 year ago

Environment

iOS 16 "react-native-vector-icons": "9.2.0", react-native: 0.70.3

Description

When building an iOS version with Hermes enable, the app crashers at startup:

Error: Font failed to load
  at apply(node_modules/react-native/Libraries/BatchedBridge/NativeModules.js:105:55)
  at ? (node_modules/react-native-vector-icons/lib/create-icon-set.js:175:13)
  at generatorResume([native code])
  at asyncGeneratorStep(node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:20)
  at _next(node_modules/@babel/runtime/helpers/asyncToGenerator.js:22:9)
  at fn(node_modules/@babel/runtime/helpers/asyncToGenerator.js:27:7)
  at tryCallTwo(node_modules/promise/setimmediate/core.js:45:5)
  at doResolve(node_modules/promise/setimmediate/core.js:200:13)
  at Promise(node_modules/promise/setimmediate/core.js:66:3)
  at apply(node_modules/@babel/runtime/helpers/asyncToGenerator.js:19:16)
  at _loadFont(node_modules/react-native-vector-icons/lib/create-icon-set.js:26:3)
  at loadFont(node_modules/react-native-vector-icons/lib/create-icon-set.js:26:3)
  at ? (src/App.js:312:12)
  at generatorResume([native code])
  at asyncGeneratorStep(node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:20)
  at _next(node_modules/@babel/runtime/helpers/asyncToGenerator.js:22:9)
  at fn(node_modules/@babel/runtime/helpers/asyncToGenerator.js:27:7)
  at tryCallTwo(node_modules/promise/setimmediate/core.js:45:5)
  at doResolve(node_modules/promise/setimmediate/core.js:200:13)
  at Promise(node_modules/promise/setimmediate/core.js:66:3)
  at apply(node_modules/@babel/runtime/helpers/asyncToGenerator.js:19:16)
  at _init(src/App.js:100:21)
  at init(src/App.js:100:21)
  at ? (src/App.js:622:11)
  at generatorResume([native code])
  at asyncGeneratorStep(node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:20)
  at _next(node_modules/@babel/runtime/helpers/asyncToGenerator.js:22:9)
  at fn(node_modules/@babel/runtime/helpers/asyncToGenerator.js:27:7)
  at tryCallTwo(node_modules/promise/setimmediate/core.js:45:5)
  at doResolve(node_modules/promise/setimmediate/core.js:200:13)
  at Promise(node_modules/promise/setimmediate/core.js:66:3)
  at apply(node_modules/@babel/runtime/helpers/asyncToGenerator.js:19:16)
  at _componentDidMountAsync(src/App.js:100:21)
  at componentDidMountAsync(src/App.js:100:21)
  at create$73(src/App.js:143:5)
  at commitHookEffectListMount(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:5828:26)
  at flushPassiveEffects(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:7532:23)
  at d(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:7371:7)
  at J(node_modules/scheduler/cjs/scheduler.production.min.js:13:203)
  at R(node_modules/scheduler/cjs/scheduler.production.min.js:14:128)
  at callback(node_modules/react-native/Libraries/Core/Timers/JSTimers.js:248:18)
  at _callTimer(node_modules/react-native/Libraries/Core/Timers/JSTimers.js:112:7)
  at _callReactNativeMicrotasksPass(node_modules/react-native/Libraries/Core/Timers/JSTimers.js:162:5)
  at _reactNativeMicrotasksCallback(node_modules/react-native/Libraries/Core/Timers/JSTimers.js:413:12)
  at __callReactNativeMicrotasks(node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:390:12)
  at fn(node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:132:12)
  at __guard(node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:367:9)
  at value(node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:131:10)
  at value([native code])
  at value([native code])

Reproducible Demo

Let us know how to reproduce the issue. Include a code sample, share a project, or share an app that reproduces the issue using https://snack.expo.io/. Please follow the guidelines for providing a MCVE: https://stackoverflow.com/help/mcve

import Icon from 'react-native-vector-icons/FontAwesome';
import EntypoIcon from 'react-native-vector-icons/Entypo';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
iBotPeaches commented 1 year ago

We aren't using Hermes, but hitting this as well. Only apparent on iOS16 according to our crash logs. Also on 9.2.0, but on RN69.

Error: Font failed to load
  at apply(node_modules/react-native/Libraries/BatchedBridge/NativeModules.js:106:55)
  at call(node_modules/react-native-vector-icons/lib/create-icon-set.js:176:13)
  at tryCatch(node_modules/regenerator-runtime/runtime.js:63:40)
  at call(node_modules/regenerator-runtime/runtime.js:294:22)
  at tryCatch(node_modules/regenerator-runtime/runtime.js:63:40)
  at invoke(node_modules/regenerator-runtime/runtime.js:155:20)
  at fn(node_modules/regenerator-runtime/runtime.js:190:11)
  at tryCallTwo(node_modules/promise/setimmediate/core.js:45:5)
  at doResolve(node_modules/promise/setimmediate/core.js:200:13)
  at Promise(node_modules/promise/setimmediate/core.js:66:3)
  at callInvokeWithMethodAndArg(node_modules/regenerator-runtime/runtime.js:189:20)
  at next(node_modules/regenerator-runtime/runtime.js:212:13)
  at async(node_modules/regenerator-runtime/runtime.js:239:14)
  at loadFont(node_modules/react-native-vector-icons/lib/create-icon-set.js:170:3)
  at factory(node_modules/react-native-dropdown-picker/src/index.js:14:9)
  at loadModuleImplementation(node_modules/metro-runtime/src/polyfills/require.js:339:5)
  at factory(App/Components/Forms/select.js:4:1)
  at loadModuleImplementation(node_modules/metro-runtime/src/polyfills/require.js:339:5)
  at factory(App/Components/Forms/index.js:2:1)
  at loadModuleImplementation(node_modules/metro-runtime/src/polyfills/require.js:339:5)
  at guardedLoadModule(node_modules/metro-runtime/src/polyfills/require.js:200:21)
  at Component(App/Components/Modules/LoadTicket/stepTicketInfo.js:154:12)
  at renderWithHooks(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:3360:13)
  at updateFunctionComponent(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:4297:15)
  at performUnitOfWork(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:6771:14)
  at workLoopSync(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:6764:37)
  at renderRootSync(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:6746:7)
  at performSyncWorkOnRoot(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:6454:20)
  at Ea([native code])
  at flushSyncCallbacks(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:2058:23)
  at scheduleUpdateOnFiber(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:6211:42)
  at jr(node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js:3829:14)
  at jr([native code])
mMarcos208 commented 1 year ago

I have the same issue, but I'm not using hermes.

WARN Possible Unhandled Promise Rejection (id: 0): Error: Font failed to load

orchsik commented 1 year ago

I have the same issue, but I'm not using hermes.

Error: Font failed to load


iOS 16 "react-native-vector-icons": "8.1.0", react-native: 0.64.0

marceloch2 commented 1 year ago

Same here.

System: Binaries: Node: 16.18.0 Watchman: 2022.10.24.00

npmPackages: react: 18.2.0 => 18.2.0 react-native: 0.69.6 => 0.69.6

tjom commented 1 year ago

This seems to be an issue with iOS 16, everything works fine for me on 15.7. The icons seem to be loading, however, despite the error.

react-native-vector-icons: 9.2.0 react: 18.1.0 react-native: 0.70.3

ghost commented 1 year ago

Same. I spent hours trying to troubleshoot this issue and got no where. Even if you async await the fontLoad() the Unhandled Promise Rejection still displays.

react-native-vector-icons: 9.1.0 React: 17.0.2 react-native: 0.68.2

brianlenz commented 1 year ago

I can confirm the same behavior. The error is only present on iOS 16+, but the font icons work in spite of the error.

react-native-vector-icons: 9.2.0 react: 18.1.0 react-native: 0.70.6

tsukudabuddha commented 1 year ago

Same here :(

Is there any known resolution? While the icons are loading, it's killing our sentry quota 😞

react-native: 0.68.5 react: 17.0.2 react-native-vector-icons: 8.1.0

tsukudabuddha commented 1 year ago

I did some debugging and it looks like the error occurs when trying to register the font (triggered by loadFont). The error is error __NSCFError * domain: @"com.apple.CoreText.CTFontManagerErrorDomain" - code: 305 0x0000600002a667c0. Not sure why this is happening, but considering the images are still working I think it would be fine to add || kCTFontManagerErrorDuplicatedName to the conditional on l:166 of RNVectorIconsManager as a short term fix for now

laurent22 commented 1 year ago

You can use this workaround to suppress the warnings:

Icon.loadFont().catch((error) => { console.info(error); });

Instead of having the useless warning in the yellow box, it will now print it to the console only. The icons still load fine with this.

gulsher7 commented 1 year ago

I have the same issue, but I'm not using hermes.

WARN Possible Unhandled Promise Rejection (id: 0): Error: Font failed to load

any luck..?

arthurgeron-work commented 1 year ago

@tsukudabuddha 's solution worked for me:

diff --git a/node_modules/react-native-vector-icons/RNVectorIconsManager/RNVectorIconsManager.m b/node_modules/react-native-vector-icons/RNVectorIconsManager/RNVectorIconsManager.m
index 2823543..2c49d26 100644
--- a/node_modules/react-native-vector-icons/RNVectorIconsManager/RNVectorIconsManager.m
+++ b/node_modules/react-native-vector-icons/RNVectorIconsManager/RNVectorIconsManager.m
@@ -163,7 +163,7 @@ - (NSString *)createGlyphImagePathForFont:(NSString *)fontName
     CFErrorRef errorRef = NULL;
     if (CTFontManagerRegisterGraphicsFont(font, &errorRef) == NO) {
       NSError *error = (__bridge NSError *)errorRef;
-      if (error.code == kCTFontManagerErrorAlreadyRegistered) {
+      if (error.code == kCTFontManagerErrorAlreadyRegistered || error.code == kCTFontManagerErrorDuplicatedName) {
         resolve(nil);
       } else {
         reject(@"font_load_failed", @"Font failed to load", error);
sawaYch commented 1 year ago

I test this issue with a bare new RN project. This issue occurs when the react-native app runs on iOS 16 or above, affecting both simulator and physical device. iOS 15.X works fine.

The rn-vector-icons version in my project:

"react-navtive-vector-icons": "9.1.0",
"react": "17.0.2",
"react-native": "0.66.4",
PunainenAurinko commented 1 year ago

@tsukudabuddha 's solution worked for me:

diff --git a/node_modules/react-native-vector-icons/RNVectorIconsManager/RNVectorIconsManager.m b/node_modules/react-native-vector-icons/RNVectorIconsManager/RNVectorIconsManager.m
index 2823543..2c49d26 100644
--- a/node_modules/react-native-vector-icons/RNVectorIconsManager/RNVectorIconsManager.m
+++ b/node_modules/react-native-vector-icons/RNVectorIconsManager/RNVectorIconsManager.m
@@ -163,7 +163,7 @@ - (NSString *)createGlyphImagePathForFont:(NSString *)fontName
     CFErrorRef errorRef = NULL;
     if (CTFontManagerRegisterGraphicsFont(font, &errorRef) == NO) {
       NSError *error = (__bridge NSError *)errorRef;
-      if (error.code == kCTFontManagerErrorAlreadyRegistered) {
+      if (error.code == kCTFontManagerErrorAlreadyRegistered || error.code == kCTFontManagerErrorDuplicatedName) {
         resolve(nil);
       } else {
         reject(@"font_load_failed", @"Font failed to load", error);

Creating a patch file with the above changes worked for my project, thanks!

tapz commented 1 year ago

createGlyphImagePathForFont in 9.2.0 is different than in the diff.

NathanielNLA commented 6 months ago

Just remove <FontName>.loadFont() it is not necessary in order to utilize the fonts!