Description
Bundling with --dev true and a --sourcemap-output set crashes with:
Error: Unexpected module with full source map found:
at processNextModule (metro-source-map/src/source-map.js)
at workLoop (metro-source-map/src/source-map.js)
at fromRawMappingsImpl (metro-source-map/src/source-map.js)
at fromRawMappingsNonBlocking (metro-source-map/src/source-map.js)
at sourceMapGeneratorNonBlocking (metro/src/DeltaBundler/Serializers/sourceMapGenerator.js)
at sourceMapStringNonBlocking (metro/src/DeltaBundler/Serializers/sourceMapString.js)
at Server._serializeGraph (metro/src/Server.js)
at Server.build (metro/src/Server.js)
at runBuild (metro/src/index.flow.js)
This reproduces reliably on an Expo SDK 56 project (metro/metro-source-map/metro-runtime 0.84.4 via @expo/metro@56.0.0, react-native@0.85.3), running:
react-native bundle --entry-file index.js --platform ios --dev true --reset-cache
--bundle-output out.jsbundle --sourcemap-output out.jsbundle.map
It is not reproducible with --dev false (with or without --minify), so this only affects development source maps, not production/release bundles.
It is not reproducible with npx expo run:ios.
It is reproducible when building through Xcode.
Root cause (as far as I could trace it)
fromRawMappingsImpl in metro-source-map/src/source-map.js throws whenever a module's map is neither an array of raw mapping tuples nor a VlqMap. In this repro, one or more modules' data.map ends up holding an object shaped like a functionMap ({__version, __count, __names, ...}) instead — i.e. the same value that correctly appears under that module's separate data.functionMap field. I was not able to fully pin down why map and functionMap end up holding the same value inside metro-transform-worker@0.84.4's per-module transform for this project — it affects a scattered, unrelated set of files (several @formatjs/* internals and a couple of plain application .js files with nothing unusual about their size or structure), which suggests a general transform-worker quirk rather than something specific to one file.
I noticed main has since replaced the result.rawMappings mechanism in metro-transform-worker with a decodedMap/tuplesFromBabelDecodedMap approach, so this exact path may already be gone upstream. However, the defensive check in metro-source-map's fromRawMappingsImpl itself is unchanged on main, and seems worth hardening regardless of the root cause: today, one module with an unexpected map shape aborts source map generation for the entire bundle, which seems more fragile than necessary.
Description
Bundling with
--dev trueand a--sourcemap-outputset crashes with:Error: Unexpected module with full source map found:
at processNextModule (metro-source-map/src/source-map.js)
at workLoop (metro-source-map/src/source-map.js)
at fromRawMappingsImpl (metro-source-map/src/source-map.js)
at fromRawMappingsNonBlocking (metro-source-map/src/source-map.js)
at sourceMapGeneratorNonBlocking (metro/src/DeltaBundler/Serializers/sourceMapGenerator.js)
at sourceMapStringNonBlocking (metro/src/DeltaBundler/Serializers/sourceMapString.js)
at Server._serializeGraph (metro/src/Server.js)
at Server.build (metro/src/Server.js)
at runBuild (metro/src/index.flow.js)
This reproduces reliably on an Expo SDK 56 project (
metro/metro-source-map/metro-runtime0.84.4via@expo/metro@56.0.0,react-native@0.85.3), running:react-native bundle --entry-file index.js --platform ios --dev true --reset-cache
--bundle-output out.jsbundle --sourcemap-output out.jsbundle.map
It is not reproducible with
--dev false(with or without--minify), so this only affects development source maps, not production/release bundles.It is not reproducible with npx expo run:ios.
It is reproducible when building through Xcode.
Root cause (as far as I could trace it)
fromRawMappingsImplinmetro-source-map/src/source-map.jsthrows whenever a module'smapis neither an array of raw mapping tuples nor aVlqMap. In this repro, one or more modules'data.mapends up holding an object shaped like afunctionMap({__version, __count, __names, ...}) instead — i.e. the same value that correctly appears under that module's separatedata.functionMapfield. I was not able to fully pin down whymapandfunctionMapend up holding the same value insidemetro-transform-worker@0.84.4's per-module transform for this project — it affects a scattered, unrelated set of files (several@formatjs/*internals and a couple of plain application.jsfiles with nothing unusual about their size or structure), which suggests a general transform-worker quirk rather than something specific to one file.I noticed
mainhas since replaced theresult.rawMappingsmechanism inmetro-transform-workerwith adecodedMap/tuplesFromBabelDecodedMapapproach, so this exact path may already be gone upstream. However, the defensive check inmetro-source-map'sfromRawMappingsImplitself is unchanged onmain, and seems worth hardening regardless of the root cause: today, one module with an unexpectedmapshape aborts source map generation for the entire bundle, which seems more fragile than necessary.