Metro resolver could not resolve an import when run via xCode or from deeper directory - works without watchman
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 5.6k
- Forks
- 696
- Avg merge
- 8m
- Merged PRs (30d)
- 7
Description
React Native version: 0.76.6
Metro version: 0.81.0
Watchman version: 2024.12.02.00
Hello. I am sorry this is long but I try to be as descriptive as possible. I am trying to upgrade RN 0.72.6 all the way up to the newest version and while I managed to make the project running when i do yarn start and press i (iOS), it just is incostent with xCode way of build. I have the react-native app in monorepo that spans multiple folders (e.g., packages/, col-mobile/, col-web/). node_modules are in the root and in the col-mobile/ folder too.
The first problem
Note: Full metro.config.js file below.
When I run the same command xCode does, in <projectDir>/col-mobile/ios:
node /Users/Martin/Tresors/Projects/<projectDir>/col-mobile/node_modules/react-native/scripts/bundle.js bundle --entry-file index.js --platform ios --dev true --reset-cache --bundle-output /Users/Martin/Library/Developer/Xcode/DerivedData/ColMobile-eefulauxzmjhbdgyseffwktprjcy/Build/Products/Debug-iphoneos/main.jsbundle --assets-dest /Users/Martin/Library/Developer/Xcode/DerivedData/ColMobile-eefulauxzmjhbdgyseffwktprjcy/Build/Products/Debug-iphoneos/ColMobile.app --config-cmd 'node /Users/Martin/Tresors/Projects/<projectDir>/col-mobile/node_modules/react-native/cli.js config'
I get the following error (note that it says "unable to resolve module packages/" without the dots at the start - ../ which might be NOT wrong but changes when I run it from the col-mobile folder):
/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:148
throw new UnableToResolveError(
^
UnableToResolveError: Unable to resolve module packages/col-tech/common/mobile/src/theme/themeConfigurations from /Users/Martin/Tresors/Projects/<projectDir>/col-mobile/App.tsx: packages/col-tech/common/mobile/src/theme/themeConfigurations could not be found within the project or in these directories:
node_modules
../node_modules
../../../../../node_modules
...
> 6 | import { loadThemeConfigurations } from "packages/col-tech/common/mobile/src/theme/themeConfigurations";
| ^
7 | import { AuthProvider } from "col-mobile/auth/AuthProvider";
...
at ModuleResolver.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:148:15)
at DependencyGraph.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph.js:235:43)
... 4 lines matching cause stack trace ...
at async Promise.all (index 3)
at async visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:92:5)
at async Promise.all (index 3)
at async visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:92:5) {
originModulePath: '/Users/Martin/Tresors/Projects/<projectDir>/col-mobile/App.tsx',
targetModuleName: 'packages/col-tech/common/mobile/src/theme/themeConfigurations',
cause: FailedToResolveNameError: Module does not exist in the Haste module map or in these directories:
/Users/Martin/Tresors/Projects/<projectDir>/col-mobile/node_modules
/Users/Martin/Tresors/Projects/<projectDir>/node_modules
/Users/Martin/Tresors/Projects/CEZ/node_modules
/Users/Martin/Tresors/Projects/node_modules
/Users/Martin/Tresors/node_modules
/Users/Martin/node_modules
/Users/node_modules
/node_modules
at Object.resolve (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro-resolver/src/resolve.js:158:9)
at resolveRequest (/Users/Martin/Tresors/Projects/<projectDir>/col-mobile/metro.config.js:64:25)
at Object.resolve (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro-resolver/src/resolve.js:35:12)
at ModuleResolver.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:73:31)
at DependencyGraph.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph.js:235:43)
at /Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/lib/transformHelpers.js:160:21
at resolveDependencies (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:42:25)
at visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:83:30)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async Promise.all (index 3) {
dirPaths: [
'/Users/Martin/Tresors/Projects/<projectDir>/col-mobile/node_modules',
'/Users/Martin/Tresors/Projects/<projectDir>/node_modules',
'/Users/Martin/Tresors/Projects/CEZ/node_modules',
'/Users/Martin/Tresors/Projects/node_modules',
'/Users/Martin/Tresors/node_modules',
'/Users/Martin/node_modules',
'/Users/node_modules',
'/node_modules'
],
extraPaths: []
}
}
But when I run the command from <projectDir>/col-mobile, it builds properly. Of course, that could be a problem with current working directory, so I tried to change the PWD at top of the metro.config.js (ugly, but worked when running from terminal):
process.chdir(__dirname, "../col-mobile/");
The metro config with chdir
const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
const path = require("path");
const process = require("process");
const resolver = require("metro-resolver");
const repositoryRoot = path.resolve(__dirname, "../col-mobile/");
// Fixes resolution when the bundler is run from ios/ directory
process.chdir(__dirname, "../col-mobile/");
/**
* Metro configuration
* https://reactnative.dev/docs/metro
*
* @type {import('metro-config').MetroConfig}
*/
const config = {
cacheStores: ({ FileStore }) => [
new FileStore({
root: path.join(__dirname, "metro-cache4"),
}),
],
transformer: {
minifierConfig: {
mangle: { toplevel: false },
output: {
ascii_only: true,
comments: false,
quote_style: 3,
wrap_iife: true,
},
sourceMap: { includeSources: false },
toplevel: false,
compress: { reduce_funcs: false },
},
},
resolver: {
useWatchman: true, // does work with watchman, but not in xCode with watchman enabled.
projectRoot: repositoryRoot,
sourceExts: ["js", "jsx", "json", "ts", "tsx"],
resolverMainFields: ["react-native", "browser", "local", "main"],
hasteImplModulePath: path.resolve(__dirname, "../col-mobile/haste.js"),
resolveRequest: (context, moduleName, platform) => {
const resolveRealPath = (absolutePath) => {
return absolutePath;
};
const resolve = (moduleName, platform) => {
return context.resolveRequest(context, moduleName, platform);
};
if (moduleName.includes("packages/")) {
const aa = resolver.resolve(context, moduleName, platform);
console.log("[AAA] " + moduleName + " and resolved is " + aa);
return aa;
}
/// ... more code here which isn't resolved for the themeConfigurations file
return resolver.resolve({ ...context, resolveRequest: resolver.resolve }, moduleName, platform);
},
},
watchFolders: [
path.join(__dirname, "../col-web/"),
path.join(__dirname, "../packages/"),
path.join(__dirname, "../node_modules"),
path.join(__dirname, "../mocks/"),
],
};
module.exports = mergeConfig(getDefaultConfig(__dirname), config);
Problem number 2
It works! But only in Terminal. When I run build in xCode, it fails searching for the themeConfigurations.ts file. The weird thing is, the error contains a full path to the file it DID NOT FIND. The file does exist though. I guess watchman didn't pick it up somehow and the lookup is through watchman I suppose. And yes, I did this command like a hundred times:
watchman watch-del '/Users/Martin/Tresors/Projects/<projectDir>/' ; watchman watch-project '/Users/Martin/Tresors/Projects/<projectDir>/'
The error (note the I guess correct "../packages"; also, look at the <-------------- line):
UnableToResolveError: Unable to resolve module ../packages/col-tech/common/mobile/src/theme/themeConfigurations from /Users/Martin/Tresors/Projects/<projectDir>/col-mobile/App.tsx:
None of these files exist:
* ../packages/col-tech/common/mobile/src/theme/themeConfigurations(.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx)
* ../packages/col-tech/common/mobile/src/theme/themeConfigurations
...
import { loadThemeConfigurations } from "packages/col-tech/common/mobile/src/theme/themeConfigurations"
...
at ModuleResolver.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:112:15)
at DependencyGraph.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph.js:235:43)
... 4 lines matching cause stack trace ...
at async Promise.all (index 3)
at async visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:92:5)
at async Promise.all (index 3)
at async visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:92:5) {
originModulePath: '/Users/Martin/Tresors/Projects/<projectDir>/col-mobile/App.tsx',
targetModuleName: '../packages/col-tech/common/mobile/src/theme/themeConfigurations',
cause: FailedToResolvePathError: The module could not be resolved because none of these files exist:
* /Users/Martin/Tresors/Projects/<projectDir>/packages/col-tech/common/mobile/src/theme/themeConfigurations(.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx) <--------------
* /Users/Martin/Tresors/Projects/<projectDir>/packages/col-tech/common/mobile/src/theme/themeConfigurations
at Object.resolve (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro-resolver/src/resolve.js:49:13)
at resolveRequest (/Users/Martin/Tresors/Projects/<projectDir>/col-mobile/metro.config.js:73:25)
at Object.resolve (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro-resolver/src/resolve.js:35:12)
at ModuleResolver.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:73:31)
at DependencyGraph.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph.js:235:43)
at /Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/lib/transformHelpers.js:160:21
at resolveDependencies (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:42:25)
at visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:83:30)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async Promise.all (index 3) {
candidates: {
file: {
type: 'sourceFile',
filePathPrefix: '../packages/col-tech/common/mobile/src/theme/themeConfigurations',
candidateExts: [
'', '.ios.js',
'.native.js', '.js',
'.ios.jsx', '.native.jsx',
'.jsx', '.ios.json',
'.native.json', '.json',
'.ios.ts', '.native.ts',
'.ts', '.ios.tsx',
'.native.tsx', '.tsx'
]
},
dir: {
type: 'sourceFile',
filePathPrefix: '../packages/col-tech/common/mobile/src/theme/themeConfigurations',
candidateExts: []
}
}
}
}
However, when I do
cat /Users/Martin/Tresors/Projects/<projectDir>/packages/col-tech/common/mobile/src/theme/themeConfigurations.ts
I get the contents of the file.
When I set useWatchman: false in the metro config, it manages to build just fine. But I guess I will lose fast refresh and so on.
What is going on? It was working in previous versions of react-native (Metro). I can give more info if needed.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with col-mobile/metro.config.js, especially its custom resolveRequest, projectRoot, watchFolders, and hasteImplModulePath settings; compare the Xcode bundle command with the working terminal invocation. Reproduce the import failure for App.tsx using the listed Metro and Watchman versions. Done means the monorepo import resolves consistently from Xcode and the terminal without relying on process.chdir().
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, react-native
- Domain
- build-system, tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100