After adding an in-house React Native PDF-viewer library, TurboModuleRegistry.getEnforcing throws that 'NativePdfViewer' could not be found; how do you diagnose whether autolinking is to blame?
answer
- is the native half in the binary?
- print the autolinking config JSON
- no podspec means skipped on iOS
- direct dependency, not transitive
- registered name must match the spec name
basics
~10 sConfirm the binary was rebuilt after install, then print the autolinking config: if the library is missing, fix discovery; if it is listed, check the native module is registered under the exact spec name.
solid answer
~40 sThe error says the name is not registered in the native binary, so split the search in two. Is the library linked at all? Rebuild after `pod install`, then run `npx @react-native-community/cli config` (or `npx expo-modules-autolinking react-native-config` in an Expo project) and check that the package appears under `dependencies` with a `podspecPath` for iOS and a source directory for Android. It is missing when it is only a transitive dependency, when its podspec is not at the package root (CocoaPods warns and skips it), or when the app's `react-native.config.js` sets that platform to `null`. If it is linked, the problem is registration: the name in `getEnforcing` must match the module's registered name on both platforms. In monorepos, also check for duplicate installs.
code
bash · 3 linesnpx @react-native-community/cli config > /tmp/rn-config.json
node -e "const c=require('/tmp/rn-config.json');console.log(JSON.stringify(c.dependencies['@my-org/pdf-viewer'], null, 2))"
yarn why react-nativego deeper
Recall that 'could not be found' usually means the native app was not rebuilt, or pod install was skipped, after adding the library.
Explain how to print the autolinking config, read each dependency's iOS and Android entries, and spot a library that is missing from it.
Separate linking failures from registration failures quickly, and know the transitive-dependency, podspec, disabled-platform and duplicate-install causes and their fixes.
Build guardrails for internal native libraries: example apps in CI, documented peers, and an install checklist so app teams do not rediscover each failure.
## Read the error literally `TurboModuleRegistry.getEnforcing('NativePdfViewer')` throws `'NativePdfViewer' could not be found. Verify that a module by this name is registered in the native binary.` The JavaScript spec loaded fine; the **native** side did not answer to that name. There are only two families of cause: 1. The library's native code is **not in the binary** (a linking problem). 2. It is in the binary but **not registered under that name** (a registration problem). The fastest diagnosis tells them apart before touching any code. ## Step 1: rule out a stale binary - Was the app rebuilt after installing the library? A Metro reload never adds native code. - On iOS, did `pod install` run afterwards, and does `Podfile.lock` list the library's pod? - In an Expo project, is this a development build made after the install, rather than an older build? ## Step 2: ask autolinking what it sees Autolinking is driven by a config command whose JSON output you can run yourself: | Project | Command | |---|---| | Bare React Native | `npx @react-native-community/cli config` | | Expo (default since SDK 52) | `npx expo-modules-autolinking react-native-config --platform ios` (or `android`) | Find the package under `dependencies`. For iOS its `platforms.ios` entry should show a `podspecPath`; for Android `platforms.android` should show a `sourceDir`. The iOS output is also written to `ios/build/generated/autolinking/autolinking.json`, and the Android one to `android/build/generated/autolinking/autolinking.json`. ## Step 3: if the library is missing - **Not a direct dependency.** The community CLI links the app's own `package.json` dependencies. If the PDF viewer arrived only through another package, add it to the app (and make it a peer dependency of that package). Expo Autolinking resolves transitive dependencies, but relying on that hides the problem from bare apps. - **No podspec found.** CocoaPods autolinking prints a warning that it skipped the dependency because no podspec file was found. The podspec must be where the config expects it, normally the package root, or declared in the library's `react-native.config.js`. - **Disabled on purpose.** An app-level `react-native.config.js` entry with `platforms: {ios: null}` removes the library from that platform. - **Not really installed.** A local library added with a file path must appear in `node_modules`, for example as a symlink, or autolinking cannot find it. ## Step 4: if the library is present Now it is a registration problem: - On Android, the module's `getName()` must return exactly `NativePdfViewer`, and its package must return the module for that name. - On iOS, the module class must be mapped to that name, typically through `ios.modulesProvider` in the library's `codegenConfig`. - The spec file must start with `Native` and live under the `codegenConfig.jsSrcsDir`, or Codegen ignores it and generates nothing for it. ## Monorepo and Expo extras - **Duplicates.** With two installed copies, JavaScript may come from one while autolinking linked the other. `npm why`, `yarn why` or `pnpm why` shows them; `npx expo-modules-autolinking verify` warns about duplicate native modules in Expo projects. - **Mixed autolinkers.** With `EXPO_USE_COMMUNITY_AUTOLINKING=1`, Expo hands React Native modules back to the community CLI, which must then be a dev dependency. ## Local libraries and monorepos In-house libraries often live beside the apps rather than in a registry, which adds two traps. First, the library must be visible to autolinking: installed into `node_modules` (a symlink from a file path works), or, in Expo projects, inside a folder listed in `expo.autolinking.searchPaths`. Second, Metro and autolinking can resolve **different copies** of the same package when it is installed twice. From SDK 54, Expo's `experiments.autolinkingModuleResolution` makes Metro use the copy autolinking linked, and SDK 55 turns it on by default for apps in monorepos. ## Make it not happen again 1. Keep an example app in the library that builds on both platforms in CI. 2. Document the peer dependencies and any `react-native.config.js` needs in the README. 3. Prefer `getEnforcing` over `get` for required modules, so a linking mistake fails loudly at startup rather than as a later null call.
- The library appears in the config on Android but not iOS. What is the usual cause?A missing or misplaced podspec. CocoaPods autolinking needs a podspec for the package and warns that it skipped the dependency when none is found. Check that the podspec ships in the published files and sits at the package root, or that the library's `react-native.config.js` points to it.
- Why prefer getEnforcing over get for a required module?`TurboModuleRegistry.get` returns null when the module is missing, so a linking mistake surfaces later as a confusing null access. `getEnforcing` throws immediately with a message naming the module and pointing at the native binary, which turns a linking bug into an obvious startup failure.
saying these in an interview costs you the question
- Clearing the Metro cache will make a missing native module appear
- Autolinking links native libraries that arrive only as transitive dependencies with the community CLI
- If autolinking lists the library, the module name cannot be the problem
- A package without a podspec is linked on iOS through its Xcode project
- The error means the TypeScript spec file failed to compile