@expo/vector-icons not loading in iOS production from bad font import

Please provide the following:

  1. SDK Version: 37.0
  2. Platforms(Android/iOS/web/all): iOS

This took me longer to figure out then I want to admit, but I still want to share in case someone else ran into this issue.

I’m using the icons from @expo/vector-icons and it works in Dev mode, Android Production but I was getting errors in iOS production which meant that Icons appeared in a box with a question mark.

After troubleshooting, I came across this error message when doing production mode in the iOS simulator

[Error: Cannot load null or undefined font source: { "16": undefined }. Expected asset of type FontSource for fontFamily of name: "16"]

Taking a closer look at the warning messages in Dev mode, I saw this, which I had initially suppressed because of all of the * Move code with side effects to componentDidMount, and set initial state in the constructor. warnings I’m used to getting. I know what you’re thinking… i know…ugh. Anyway, that led me to find this warning message:

Cannot load null or undefined font source: { "16": undefined }. Expected asset of type `FontSource` for fontFamily of name: "16"
* [native code]:null in construct
- node_modules/@babel/runtime/helpers/construct.js:30:26 in _construct
- node_modules/@babel/runtime/helpers/wrapNativeSuper.js:26:23 in Wrapper
- node_modules/@unimodules/react-native-adapter/build/errors/CodedError.js:8:8 in constructor
- node_modules/expo-font/build/Font.js:75:14 in loadFontInNamespaceAsync
- node_modules/regenerator-runtime/runtime.js:45:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:271:30 in invoke
- node_modules/regenerator-runtime/runtime.js:45:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:135:28 in invoke
- node_modules/regenerator-runtime/runtime.js:170:17 in Promise$argument_0
- node_modules/promise/setimmediate/core.js:45:7 in tryCallTwo
- node_modules/promise/setimmediate/core.js:200:23 in doResolve
- node_modules/promise/setimmediate/core.js:66:12 in Promise
- node_modules/regenerator-runtime/runtime.js:169:27 in Promise$argument_0
- node_modules/regenerator-runtime/runtime.js:192:38 in enqueue
- node_modules/regenerator-runtime/runtime.js:216:8 in exports.async
- node_modules/expo-font/build/Font.js:73:0 in loadFontInNamespaceAsync
- node_modules/expo-font/build/Font.js:71:42 in loadAsync
- node_modules/regenerator-runtime/runtime.js:45:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:271:30 in invoke
- node_modules/regenerator-runtime/runtime.js:45:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:135:28 in invoke
- node_modules/regenerator-runtime/runtime.js:170:17 in Promise$argument_0
- node_modules/promise/setimmediate/core.js:45:7 in tryCallTwo
- node_modules/promise/setimmediate/core.js:200:23 in doResolve
- node_modules/promise/setimmediate/core.js:66:12 in Promise
- node_modules/regenerator-runtime/runtime.js:169:27 in Promise$argument_0
- node_modules/regenerator-runtime/runtime.js:192:38 in enqueue
- node_modules/regenerator-runtime/runtime.js:216:8 in exports.async
- node_modules/expo-font/build/Font.js:61:7 in loadAsync
* src/boot/setup.js:17:19 in fonts.map$argument_0
* [native code]:null in map
* src/boot/setup.js:16:0 in cacheFonts
* http://127.0.0.1:19001/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false:124120:40 in _loadAssetsAsync$
- node_modules/regenerator-runtime/runtime.js:45:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:271:30 in invoke
- node_modules/regenerator-runtime/runtime.js:45:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:135:28 in invoke
- node_modules/regenerator-runtime/runtime.js:170:17 in Promise$argument_0
- node_modules/promise/setimmediate/core.js:45:7 in tryCallTwo
- node_modules/promise/setimmediate/core.js:200:23 in doResolve
- node_modules/promise/setimmediate/core.js:66:12 in Promise
- node_modules/regenerator-runtime/runtime.js:169:27 in Promise$argument_0
- node_modules/regenerator-runtime/runtime.js:192:38 in enqueue
- node_modules/regenerator-runtime/runtime.js:216:8 in exports.async
* http://127.0.0.1:19001/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false:124116:42 in _loadAssetsAsync
- node_modules/expo/build/launch/AppLoading.js:8:46 in _startLoadingAppResourcesAsync
- node_modules/regenerator-runtime/runtime.js:45:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:271:30 in invoke
- node_modules/regenerator-runtime/runtime.js:45:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:135:28 in invoke
- node_modules/regenerator-runtime/runtime.js:170:17 in Promise$argument_0
- node_modules/promise/setimmediate/core.js:45:7 in tryCallTwo
- node_modules/promise/setimmediate/core.js:200:23 in doResolve
- node_modules/promise/setimmediate/core.js:66:12 in Promise
- node_modules/regenerator-runtime/runtime.js:169:27 in Promise$argument_0
- node_modules/regenerator-runtime/runtime.js:192:38 in enqueue
- node_modules/regenerator-runtime/runtime.js:216:8 in exports.async
- node_modules/expo/build/launch/AppLoading.js:8:8 in constructor
- node_modules/expo/build/launch/AppLoading.js:41:35 in componentDidMount
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:17029:10 in commitLifeCycles
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:20002:23 in commitLayoutEffects
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:307:15 in invokeGuardedCallbackImpl
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:531:36 in invokeGuardedCallback
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:19768:10 in commitRootImpl
* [native code]:null in commitRootImpl
- node_modules/react-native/node_modules/scheduler/cjs/scheduler.development.js:643:23 in unstable_runWithPriority
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:19590:4 in commitRoot
* [native code]:null in commitRoot
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:18709:28 in runRootCallback
* [native code]:null in runRootCallback
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:5642:32 in runWithPriority$argument_1
- node_modules/react-native/node_modules/scheduler/cjs/scheduler.development.js:643:23 in unstable_runWithPriority
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:5638:22 in flushSyncCallbackQueueImpl
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:5627:28 in flushSyncCallbackQueue
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:18851:26 in flushSync
- node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js:6416:14 in flushSync$argument_0
- node_modules/react-refresh/cjs/react-refresh-runtime.development.js:218:32 in mountedRoots.forEach$argument_0
* [native code]:null in forEach
- node_modules/react-refresh/cjs/react-refresh-runtime.development.js:210:25 in mountedRoots.forEach$argument_0
- node_modules/react-native/Libraries/Core/setUpReactRefresh.js:43:6 in Refresh.performReactRefresh
- node_modules/metro/src/lib/polyfills/require.js:609:10 in setTimeout$argument_0
- node_modules/react-native/Libraries/Core/Timers/JSTimers.js:146:14 in _callTimer
- node_modules/react-native/Libraries/Core/Timers/JSTimers.js:399:17 in callTimers
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:436:47 in __callFunction
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:111:26 in __guard$argument_0
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:384:10 in __guard
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:110:17 in __guard$argument_0
* [native code]:null in callFunctionReturnFlushedQueue

What was happening, is that in Dev Mode, I was getting a good warning but the icons were loading. In production mode, the warning turned into an error and would not load the icons.

The code responsible looks like this:

import Roboto from "./fonts/Roboto.ttf";
import Roboto_medium from "./fonts/Roboto_medium.ttf";
import { Ionicons, FontAwesome, SimpleLineIcons, MaterialIcons, MaterialCommunityIcons, AntDesign, Octicons } from "@expo/vector-icons";

...

function cacheFonts(fonts) {
  return fonts.map(font => Font.loadAsync(font)); // Where the warning is coming from
}

...

async _loadAssetsAsync() {
    const fontAssets = cacheFonts([
      Roboto,
      Roboto_medium,
      Ionicons.font,
      FontAwesome.font,
      SimpleLineIcons.font,
      MaterialIcons.font,
      MaterialCommunityIcons.font,
      AntDesign.font,
      Octicons.font
    ]);
    await Promise.all([...fontAssets]);
  }

This code is almost identical to the one in the docs here https://docs.expo.io/guides/preloading-and-caching-assets/ for preloading assets.

On to my silly mistake. The Roboto, and Robot_medium import references were bad. There were no import Roboto from "./fonts/Roboto.ttf"; import Roboto_medium from "./fonts/Roboto_medium.ttf"; font files to load.

Removing the references to Roboto font fixed both the warning and the error. I’m going to republish and check to make sure it is fully fixed. :slight_smile:

can you share a https://stackoverflow.com/help/mcve project please?

I’ll see if I can put one together.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.