Repository navigation
[0.87.0] VirtualizedList triggers Metro package-exports warning #57933
Description
Description
Actual: A fresh React Native 0.87.0 app rendering the public FlatList API makes Metro emit the warning below. Metro falls back to file-based resolution and completes the bundle, but the app itself uses only public React Native APIs.
The import comes from the first-party @react-native/virtualized-lists@0.87.0 package, a direct dependency of react-native@0.87.0. It deep-imports react-native/src/private/featureflags/ReactNativeFeatureFlags in VirtualizedList.js:67 and VirtualizeUtils.js:16. React Native 0.86 exported ./src/*, so this import did not violate its package exports map. PR #57484 removed that mapping for 0.87.0, while both imports remain in 0.87.0 and on main as of 2026-08-13.
Expected: A fresh app using FlatList should bundle without a package-exports warning. The internal imports should use an exported entry point, or react-native should export the subpath they require.
Steps to reproduce
- Clone the public reproducer made from the official React Native reproducer template and enter the app:
git clone https://github.com/wojtekmaj/react-native-087-virtualized-lists-exports-repro.git && cd react-native-087-virtualized-lists-exports-repro/ReproducerApp - Install the locked dependencies:
npx yarn@1.22.22 install --frozen-lockfile - Run a deterministic iOS Metro bundle (no simulator is required):
npx react-native bundle --platform ios --dev true --entry-file index.js --bundle-output /tmp/ReproducerApp.jsbundle --assets-dest /tmp/ReproducerApp-assets - Metro prints the package-exports warning, then writes the bundle using file-based resolution.
React Native Version
0.87.0
Affected Platforms
Runtime - iOS, Build - MacOS
Output of npx @react-native-community/cli info
info Fetching system and libraries information...
System:
OS: macOS 26.6.1
CPU: (10) arm64 Apple M1 Max
Memory: 144.61 MB / 64.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 24.17.0
path: /usr/local/bin/node
Yarn:
version: 4.17.1
path: /usr/local/bin/yarn
npm:
version: 11.13.0
path: /usr/local/bin/npm
Watchman: Not Found
Managers:
CocoaPods:
version: 1.16.2
path: /opt/homebrew/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 25.5
- iOS 26.5
- macOS 26.5
- tvOS 26.5
- visionOS 26.5
- watchOS 26.5
Android SDK: Not Found
IDEs:
Android Studio: Not Found
Xcode:
version: 26.6/17F113
path: /usr/bin/xcodebuild
Languages:
Java: Not Found
Ruby:
version: 2.6.10
path: /usr/bin/ruby
npmPackages:
"@react-native-community/cli":
installed: 20.2.0
wanted: 20.2.0
react:
installed: 19.2.3
wanted: 19.2.3
react-native:
installed: 0.87.0
wanted: 0.87.0
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: Not found
newArchEnabled: Not found
iOS:
hermesEnabled: true
newArchEnabled: true
Stacktrace or Logs
WARN Attempted to import the module "/path/to/ReproducerApp/node_modules/react-native/src/private/featureflags/ReactNativeFeatureFlags" which is not listed in the "exports" of "/path/to/ReproducerApp/node_modules/react-native" under the requested subpath "./src/private/featureflags/ReactNativeFeatureFlags". Falling back to file-based resolution. Consider updating the call site or asking the package maintainer(s) to expose this API.
MANDATORY Reproducer
https://github.com/wojtekmaj/react-native-087-virtualized-lists-exports-repro
Screenshots and Videos
Not applicable. The complete normalized warning is included above.
Activity
[-][0.87.0] @react-native/virtualized-lists triggers Metro package-exports warning for ReactNativeFeatureFlags[/-][+][0.87.0] VirtualizedList triggers Metro package-exports warning[/+]brentvatne commentedon Aug 26, 2026
expo-bot commentedon Aug 26, 2026
Proposed fix — 1 file, 15 diff lines. This patch was produced by the verification run for #57933 (requested by @brentvatne) and has not been run through this repository's CI; treat it as a starting point for a maintainer, not a landed change.
Export the
ReactNativeFeatureFlagssubpath used by@react-native/virtualized-listsSummary:
A fresh React Native 0.87.0 app that renders the public
FlatListAPI makes Metro print a package-exports warning, reported in #57933:@react-native/virtualized-listsis a separate npm package. It reaches React Native only through thereact-nativepackageexportsmap, and it importsreact-native/src/private/featureflags/ReactNativeFeatureFlagsin two shipped files —Lists/VirtualizedList.js#L67andLists/VirtualizeUtils.js#L16— plus one test file,Lists/__tests__/VirtualizeUtils-test.js#L21. It reads the JS-only flagsdeferFlatListFocusChangeRenderUpdateandfixVirtualizeListCollapseWindowSize.#57484 (commit f0bb9de) removed the
"./src/*"mapping frompackages/react-native/package.json. The summary of that pull request says these import paths "were never used externally", and its one listed caveat isrn-tester. The cross-package import from@react-native/virtualized-listswas missed, so the subpath became unlisted while both call sites stayed.FlatList,SectionListandVirtualizedListall loadVirtualizedList.js, so any app that renders a list hits the warning.This change adds back that one exact subpath. It does not restore the
"./src/*"wildcard.Nothing breaks at runtime today, because Metro falls back to file-based resolution. The cost is a warning on every bundle of an app that uses a core public component, and a dependence on a resolver fallback that stricter resolvers do not provide.
Changelog:
[GENERAL] [FIXED] - Fix Metro package-exports warning when rendering
FlatList, by exporting thereact-native/src/private/featureflags/ReactNativeFeatureFlagssubpath that@react-native/virtualized-listsimportsTest Plan:
Reproducer from #57933, unmodified, on Node 24.19.0 and yarn 1.22.22 (Linux):
The only variable between the runs below is the four added lines, applied to
node_modules/react-native/package.jsonin that app. All four arms used--reset-cache.exportsentryd5a5f226c40d8ae791bfc79022b3bfe6d5a5f226c40d8ae791bfc79022b3bfe6d7fe9c93b2399e101f4eae44b06faec1d7fe9c93b2399e101f4eae44b06faec1On each platform the two bundles are byte-identical. The change removes the warning and does not change what Metro resolves.
Repository checks, run in a clean checkout of
mainat ea06a31 with the change applied:npx prettier --check packages/react-native/package.json—All matched files use Prettier code style!yarn jest packages/virtualized-lists— 8 suites passed, 172 passed / 1 skipped, 69 snapshots passedyarn flow-check—Found 0 errorsyarn test— 224 suites passed, 5845 passed / 1 skipped, 1681 snapshots passedscripts/build/build.jsis the only tool in the repository that reads anexportsmap, and it validates only packages listed inscripts/build/config.js.react-nativeis not one of them, so the new entry needs no.flow.jswrapper.Options considered
"./src/private/featureflags/ReactNativeFeatureFlags"to theexportsmap. Chosen: it is four lines, it changes no resolution result (byte-identical bundles above), it keeps the"./src/*"wildcard removed, and it also covers third-party code that follows the import path documented insrc/private/featureflags/__docs__/README.md."./src/*"wildcard that Remove src/* exports mapping (#57484) #57484 removed. Cost: it re-lists every file undersrc/, including all ofsrc/private/, as a package entry point. That is the exact mapping Remove src/* exports mapping (#57484) #57484 set out to delete. Rejected: it reverts a deliberate change instead of correcting one missed call site../react-private-interface. Cost: one new source file inpackages/react-native/src, a newexportsentry, and three changed import sites inpackages/virtualized-lists. It also leaves the documented import path unlisted for everyone else. Rejected: choosing the name and the scope of a new entry point is a design decision for the maintainers.FlatList,SectionListorVirtualizedListkeeps printing the warning, and correct resolution keeps depending on the Metro fallback. Rejected: the warning names an internal path that the app author cannot act on.Patch (packages/react-native/package.json)
Run: (no run url)
Expose ReactNativeFeatureFlags through react-private-interface (react…
Expose ReactNativeFeatureFlags through react-private-interface (react…
Expose ReactNativeFeatureFlags through react-private-interface (#57940)
Expose ReactNativeFeatureFlags through react-private-interface (react…