Summary
When a dependency (e.g. react-native-calendars) ships image assets only as platform-specific files (e.g. previous@2x.ios.png and previous@2x.android.png) and no generic file (e.g. previous@2x.png), the Metro dev server returns 404 and throws:
Error: 'node_modules/react-native-calendars/src/calendar/img/previous@2x.png' could not be found, because it is not within the projectRoot or watchFolders, or it is blocked via the resolver.blockList config at getAsset (/path/to/node_modules/metro/src/Assets.js:226:13) at Server._processSingleAssetRequest (/path/to/node_modules/metro/src/Server.js:443:47)
The same happens for next@2x.png. Production/release builds work; the failure is development only (asset served by Metro on demand).
Environment
- React Native: 0.83.x
- Metro: 0.83.5 (likely 0.83.4+)
- Package: e.g.
react-native-calendars@1.1314.0 (assets under node_modules/.../src/calendar/img/)
Current behavior
- The app uses
require('../img/previous.png') from the dependency (or equivalent).
- At runtime in dev, the client requests the asset by a path like
.../img/previous@2x.png (generic density name, no platform suffix).
- In
getAsset(), Metro uses fileExistsInFileMap(absolutePath) for that exact path.
- On disk the package only has
previous@2x.ios.png and previous@2x.android.png, so previous@2x.png is not in the file map.
- The check fails and Metro throws the error above instead of resolving to the platform-specific asset (e.g. via
getAbsoluteAssetRecord() / platform resolution).
So the failure is due to validating the requested path (generic @2x.png) against the file map, instead of treating it as a base name and resolving to the platform-specific file that actually exists.
Expected behavior
When the requested path is a “logical” asset name (e.g. .../previous@2x.png) and the package only ships platform-specific files (previous@2x.ios.png, previous@2x.android.png), Metro should either:
- Resolve the requested path to the correct platform-specific asset before the
fileExistsInFileMap check, or
- Allow the request when a corresponding platform-specific file exists for that base name,
so that dev server asset serving is consistent with how the bundler resolves platform-specific assets at build time.
Related
- Same pattern reported for
@react-navigation/elements and back-icon@3x.png: #1667.
- Affected package (example):
react-native-calendars – only has previous@2x.ios.png / previous@2x.android.png and next@2x.ios.png / next@2x.android.png, no generic previous@2x.png / next@2x.png.
Summary
When a dependency (e.g.
react-native-calendars) ships image assets only as platform-specific files (e.g.previous@2x.ios.pngandprevious@2x.android.png) and no generic file (e.g.previous@2x.png), the Metro dev server returns 404 and throws:Error: 'node_modules/react-native-calendars/src/calendar/img/previous@2x.png' could not be found, because it is not within the projectRoot or watchFolders, or it is blocked via the resolver.blockList config at getAsset (/path/to/node_modules/metro/src/Assets.js:226:13) at Server._processSingleAssetRequest (/path/to/node_modules/metro/src/Server.js:443:47)The same happens for
next@2x.png. Production/release builds work; the failure is development only (asset served by Metro on demand).Environment
react-native-calendars@1.1314.0(assets undernode_modules/.../src/calendar/img/)Current behavior
require('../img/previous.png')from the dependency (or equivalent)..../img/previous@2x.png(generic density name, no platform suffix).getAsset(), Metro usesfileExistsInFileMap(absolutePath)for that exact path.previous@2x.ios.pngandprevious@2x.android.png, soprevious@2x.pngis not in the file map.getAbsoluteAssetRecord()/ platform resolution).So the failure is due to validating the requested path (generic
@2x.png) against the file map, instead of treating it as a base name and resolving to the platform-specific file that actually exists.Expected behavior
When the requested path is a “logical” asset name (e.g.
.../previous@2x.png) and the package only ships platform-specific files (previous@2x.ios.png,previous@2x.android.png), Metro should either:fileExistsInFileMapcheck, orso that dev server asset serving is consistent with how the bundler resolves platform-specific assets at build time.
Related
@react-navigation/elementsandback-icon@3x.png: #1667.react-native-calendars– only hasprevious@2x.ios.png/previous@2x.android.pngandnext@2x.ios.png/next@2x.android.png, no genericprevious@2x.png/next@2x.png.