0
# Error Handling
1
2
Metro Resolver provides comprehensive error types for different resolution failure scenarios with detailed diagnostic information. Each error type includes specific information to help debug resolution issues.
3
4
## Capabilities
5
6
### FailedToResolveNameError
7
8
Error thrown when a module name cannot be resolved in the Haste module map or through node_modules lookup.
9
10
```typescript { .api }
11
class FailedToResolveNameError extends Error {
12
/** Node modules directories that were searched */
13
dirPaths: ReadonlyArray<string>;
14
15
/** Additional paths that were searched (e.g., extraNodeModules) */
16
extraPaths: ReadonlyArray<string>;
17
18
constructor(
19
dirPaths: ReadonlyArray<string>,
20
extraPaths: ReadonlyArray<string>
21
);
22
}
23
```
24
25
**Usage Example:**
26
27
```javascript
28
const Resolver = require("metro-resolver");
29
30
try {
31
const result = Resolver.resolve(context, 'non-existent-package', null);
32
} catch (error) {
33
if (error instanceof Resolver.FailedToResolveNameError) {
34
console.log('Searched directories:', error.dirPaths);
35
console.log('Extra paths:', error.extraPaths);
36
console.log('Error message:', error.message);
37
}
38
}
39
```
40
41
### FailedToResolvePathError
42
43
Error thrown when a specific file path cannot be resolved (for relative or absolute imports).
44
45
```typescript { .api }
46
class FailedToResolvePathError extends Error {
47
/** File and directory candidates that were attempted */
48
candidates: FileAndDirCandidates;
49
50
constructor(candidates: FileAndDirCandidates);
51
}
52
53
interface FileAndDirCandidates {
54
readonly dir: FileCandidates;
55
readonly file: FileCandidates;
56
}
57
```
58
59
**Usage Example:**
60
61
```javascript
62
try {
63
const result = Resolver.resolve(context, './missing-file', 'ios');
64
} catch (error) {
65
if (error instanceof Resolver.FailedToResolvePathError) {
66
console.log('File candidates:', error.candidates.file);
67
console.log('Directory candidates:', error.candidates.dir);
68
}
69
}
70
```
71
72
### InvalidPackageError
73
74
Error thrown when a package.json has an invalid main field that cannot be resolved.
75
76
```typescript { .api }
77
class InvalidPackageError extends Error {
78
/** File candidates attempted for the main field */
79
fileCandidates: FileCandidates;
80
81
/** Index file candidates attempted as fallback */
82
indexCandidates: FileCandidates;
83
84
/** Full path to the main module that was attempted */
85
mainModulePath: string;
86
87
/** Full path to the package.json file */
88
packageJsonPath: string;
89
90
constructor(opts: {
91
fileCandidates: FileCandidates;
92
indexCandidates: FileCandidates;
93
mainModulePath: string;
94
packageJsonPath: string;
95
});
96
}
97
```
98
99
**Usage Example:**
100
101
```javascript
102
try {
103
const result = Resolver.resolve(context, 'broken-package', null);
104
} catch (error) {
105
if (error instanceof Resolver.InvalidPackageError) {
106
console.log('Package.json path:', error.packageJsonPath);
107
console.log('Main module path:', error.mainModulePath);
108
console.log('File candidates:', error.fileCandidates);
109
console.log('Index candidates:', error.indexCandidates);
110
}
111
}
112
```
113
114
### FailedToResolveUnsupportedError
115
116
Error thrown when resolution encounters unsupported scenarios.
117
118
```typescript { .api }
119
class FailedToResolveUnsupportedError extends Error {
120
constructor(message: string);
121
}
122
```
123
124
### Package Export/Import Errors
125
126
Specialized errors for package.json exports and imports field resolution failures.
127
128
```typescript { .api }
129
class PackagePathNotExportedError extends Error {
130
/** The package path that is not exported */
131
packagePath: string;
132
133
/** The subpath that was requested */
134
subpath: string;
135
136
constructor(opts: {
137
packagePath: string;
138
subpath: string;
139
});
140
}
141
142
class PackageImportNotResolvedError extends Error {
143
/** The import specifier that could not be resolved */
144
importSpecifier: string;
145
146
/** Reason for the resolution failure */
147
reason: string;
148
149
constructor(opts: {
150
importSpecifier: string;
151
reason: string;
152
});
153
}
154
155
class InvalidPackageConfigurationError extends Error {
156
/** Details about the invalid configuration */
157
reason: string;
158
159
constructor(reason: string);
160
}
161
```
162
163
### File Candidates System
164
165
The resolver tracks attempted file paths to provide detailed error information.
166
167
```typescript { .api }
168
type FileCandidates =
169
| { readonly type: 'asset'; readonly name: string }
170
| {
171
readonly type: 'sourceFile';
172
filePathPrefix: string;
173
readonly candidateExts: ReadonlyArray<string>;
174
};
175
176
interface FileAndDirCandidates {
177
readonly dir: FileCandidates;
178
readonly file: FileCandidates;
179
}
180
```
181
182
### Format File Candidates
183
184
Utility function to format file candidates for human-readable error messages.
185
186
```typescript { .api }
187
/**
188
* Format file candidates into a human-readable string
189
* @param candidates - File candidates to format
190
* @returns Formatted string representation
191
*/
192
function formatFileCandidates(candidates: FileCandidates): string;
193
```
194
195
**Usage Examples:**
196
197
```javascript
198
const { formatFileCandidates } = require("metro-resolver");
199
200
// For source file candidates
201
const sourceCandidates = {
202
type: 'sourceFile',
203
filePathPrefix: '/app/src/component',
204
candidateExts: ['.ios.js', '.native.js', '.js', '.ts']
205
};
206
207
console.log(formatFileCandidates(sourceCandidates));
208
// Output: "/app/src/component(.ios.js|.native.js|.js|.ts)"
209
210
// For asset candidates
211
const assetCandidates = {
212
type: 'asset',
213
name: 'icon.png'
214
};
215
216
console.log(formatFileCandidates(assetCandidates));
217
// Output: "icon.png"
218
```
219
220
### Error Handling Best Practices
221
222
When working with Metro Resolver errors, follow these patterns:
223
224
**Comprehensive Error Handling:**
225
226
```javascript
227
const Resolver = require("metro-resolver");
228
229
function resolveWithErrorHandling(context, moduleName, platform) {
230
try {
231
return Resolver.resolve(context, moduleName, platform);
232
} catch (error) {
233
if (error instanceof Resolver.FailedToResolveNameError) {
234
console.error(`Failed to resolve module "${moduleName}"`);
235
console.error('Searched in directories:', error.dirPaths);
236
console.error('Additional paths:', error.extraPaths);
237
} else if (error instanceof Resolver.FailedToResolvePathError) {
238
console.error(`Failed to resolve path "${moduleName}"`);
239
console.error('File candidates:', Resolver.formatFileCandidates(error.candidates.file));
240
console.error('Directory candidates:', Resolver.formatFileCandidates(error.candidates.dir));
241
} else if (error instanceof Resolver.InvalidPackageError) {
242
console.error(`Invalid package configuration`);
243
console.error('Package:', error.packageJsonPath);
244
console.error('Main module:', error.mainModulePath);
245
} else {
246
console.error('Unexpected resolution error:', error.message);
247
}
248
throw error;
249
}
250
}
251
```
252
253
**Error Recovery Strategies:**
254
255
```javascript
256
function resolveWithFallback(context, moduleName, platform) {
257
try {
258
return Resolver.resolve(context, moduleName, platform);
259
} catch (error) {
260
if (error instanceof Resolver.FailedToResolveNameError) {
261
// Try without platform-specific resolution
262
if (platform) {
263
try {
264
return Resolver.resolve(context, moduleName, null);
265
} catch (fallbackError) {
266
// Handle nested error
267
}
268
}
269
}
270
throw error;
271
}
272
}
273
```
274
275
### Warning System
276
277
The resolver includes a warning system for non-fatal issues.
278
279
```typescript { .api }
280
interface WarningConfiguration {
281
/** Function to handle warning messages */
282
unstable_logWarning: (message: string) => void;
283
}
284
```
285
286
**Common Warning Scenarios:**
287
- Package exports field resolution failures (with fallback to file-based resolution)
288
- Package imports field resolution failures (with fallback to file-based resolution)
289
- Invalid package configuration (with fallback)
290
291
**Usage Example:**
292
293
```javascript
294
const context = {
295
// ... other config
296
unstable_logWarning: (message) => {
297
console.warn(`[Metro Resolver Warning]: ${message}`);
298
}
299
};
300
```