0
# Error Handling
1
2
Metro Transform Worker provides comprehensive error handling with detailed context and debugging information for transformation failures.
3
4
## Capabilities
5
6
### Invalid Require Call Errors
7
8
Specialized error handling for malformed require() calls detected during dependency analysis.
9
10
```javascript { .api }
11
class InvalidRequireCallError extends Error {
12
/** Original error from Metro's dependency collection system */
13
innerError: InternalInvalidRequireCallError;
14
/** File path where the invalid require call was found */
15
filename: string;
16
17
/**
18
* Creates an error for invalid require() call syntax
19
* @param innerError - Original error from dependency analysis
20
* @param filename - File containing the invalid require call
21
*/
22
constructor(innerError: InternalInvalidRequireCallError, filename: string);
23
}
24
```
25
26
**Usage Examples:**
27
28
```javascript
29
const { transform } = require("metro-transform-worker");
30
31
try {
32
const result = await transform(config, projectRoot, filename, data, options);
33
} catch (error) {
34
if (error instanceof InvalidRequireCallError) {
35
console.error(`Invalid require call in ${error.filename}`);
36
console.error(`Details: ${error.innerError.message}`);
37
console.error(`Location: Line ${error.innerError.line}, Column ${error.innerError.column}`);
38
}
39
}
40
```
41
42
### Common Error Scenarios
43
44
#### Invalid Require Syntax
45
46
Metro Transform Worker detects and reports various invalid require() call patterns:
47
48
```javascript
49
// Invalid: Dynamic require with non-literal argument
50
const moduleName = "some-module";
51
require(moduleName); // Throws InvalidRequireCallError
52
53
// Invalid: Computed property access in require
54
require("module")[computedProperty]; // Throws InvalidRequireCallError
55
56
// Invalid: Require in unsupported context
57
if (condition) {
58
require("conditional-module"); // May throw depending on config
59
}
60
61
// Valid: Static require calls
62
require("some-module");
63
const { method } = require("some-module");
64
```
65
66
#### Reserved String Conflicts
67
68
Metro reserves certain strings for internal use and validates source code doesn't contain them:
69
70
```javascript { .api }
71
// Reserved strings that trigger SyntaxError:
72
const reservedStrings = [
73
"_$$_METRO_MODULE_ID", // Used when unstable_staticHermesOptimizedRequire is enabled
74
// Custom dependency map name from config.unstable_dependencyMapReservedName
75
];
76
```
77
78
**Error handling:**
79
80
```javascript
81
try {
82
const result = await transform(config, projectRoot, filename, data, options);
83
} catch (error) {
84
if (error instanceof SyntaxError && error.message.includes("reserved string")) {
85
console.error("Source code contains reserved Metro string");
86
console.error(`String: ${error.message.match(/`([^`]+)`/)[1]}`);
87
console.error(`Position: ${error.message.match(/character offset (\d+)/)[1]}`);
88
}
89
}
90
```
91
92
#### Minification Errors
93
94
Detailed error reporting for minification failures with file context:
95
96
```javascript
97
// Minification error handling
98
try {
99
const result = await transform(config, projectRoot, filename, data, {
100
...options,
101
minify: true,
102
});
103
} catch (error) {
104
if (error.constructor.name === "JS_Parse_Error") {
105
// Terser/minifier syntax error with enhanced context
106
console.error(`Minification failed in ${filename}`);
107
console.error(`Error: ${error.message}`);
108
console.error(`Location: Line ${error.line}, Column ${error.col}`);
109
}
110
}
111
```
112
113
#### Babel Transformation Errors
114
115
Babel transformation failures are propagated with original error context:
116
117
```javascript
118
try {
119
const result = await transform(config, projectRoot, filename, data, options);
120
} catch (error) {
121
if (error.name === "SyntaxError" && error.loc) {
122
console.error(`Babel transformation failed in ${filename}`);
123
console.error(`Error: ${error.message}`);
124
console.error(`Location: Line ${error.loc.line}, Column ${error.loc.column}`);
125
}
126
}
127
```
128
129
### Error Context and Debugging
130
131
#### File Context
132
133
All transformation errors include comprehensive file context:
134
135
```javascript { .api }
136
interface ErrorContext {
137
/** Original filename being transformed */
138
filename: string;
139
/** Project root directory */
140
projectRoot: string;
141
/** Transformation configuration */
142
config: JsTransformerConfig;
143
/** Transform options that led to error */
144
options: JsTransformOptions;
145
}
146
```
147
148
#### Stack Trace Preservation
149
150
Metro Transform Worker preserves original error stack traces while adding context:
151
152
```javascript
153
// Original error from Babel or minifier
154
const originalError = new SyntaxError("Unexpected token");
155
originalError.line = 42;
156
originalError.column = 15;
157
158
// Enhanced error with file context
159
const enhancedError = new Error(
160
`${originalError.message} in file ${filename} at ${originalError.line}:${originalError.column}`
161
);
162
enhancedError.stack = originalError.stack; // Preserve original stack
163
```
164
165
#### Configuration Debugging
166
167
When errors occur due to configuration issues:
168
169
```javascript
170
// Configuration validation errors
171
try {
172
const minifier = getMinifier(config.minifierPath);
173
} catch (error) {
174
throw new Error(
175
`A problem occurred while trying to fetch the minifier. ` +
176
`Path: "${config.minifierPath}", error message: ${error.message}`
177
);
178
}
179
```
180
181
### Error Recovery Strategies
182
183
#### Graceful Degradation
184
185
Metro Transform Worker attempts graceful degradation for non-critical failures:
186
187
```javascript
188
// Optional feature failures don't crash entire transformation
189
try {
190
// Apply optimization plugins
191
applyOptimizations(ast, config);
192
} catch (optimizationError) {
193
// Continue without optimizations
194
console.warn(`Optimization failed: ${optimizationError.message}`);
195
}
196
```
197
198
#### Partial Success Handling
199
200
Some transformations can succeed partially:
201
202
```javascript { .api }
203
interface PartialTransformResult {
204
/** Successfully transformed output (may be incomplete) */
205
output: ReadonlyArray<JsOutput>;
206
/** Dependencies that were successfully extracted */
207
dependencies: ReadonlyArray<TransformResultDependency>;
208
/** Non-fatal warnings and issues */
209
warnings: ReadonlyArray<string>;
210
}
211
```
212
213
### Error Reporting Best Practices
214
215
#### Structured Error Information
216
217
```javascript
218
// Comprehensive error reporting
219
function handleTransformError(error, context) {
220
const errorReport = {
221
type: error.constructor.name,
222
message: error.message,
223
filename: context.filename,
224
location: error.loc || { line: error.line, column: error.column },
225
transformOptions: context.options,
226
configHash: getCacheKey(context.config),
227
stack: error.stack,
228
};
229
230
console.error("Transform Error:", JSON.stringify(errorReport, null, 2));
231
232
// Report to error tracking service
233
reportError(errorReport);
234
}
235
```
236
237
#### Development vs Production Error Handling
238
239
```javascript
240
if (options.dev) {
241
// Development: Detailed error information
242
throw new Error(`
243
Transformation failed: ${error.message}
244
File: ${filename}
245
Line: ${error.line}, Column: ${error.column}
246
Config: ${JSON.stringify(config, null, 2)}
247
Stack: ${error.stack}
248
`);
249
} else {
250
// Production: Concise error without sensitive information
251
throw new Error(`Transformation failed in ${path.basename(filename)}: ${error.message}`);
252
}
253
```
254
255
### Integration with Metro Error Handling
256
257
Metro Transform Worker errors integrate with Metro's error reporting system:
258
259
```javascript
260
// Metro configuration for error handling
261
const metroConfig = {
262
transformer: {
263
// Transform worker will throw errors that Metro catches and reports
264
getTransformOptions: () => transformOptions,
265
},
266
reporter: {
267
// Custom reporter can handle transform worker errors
268
update: (event) => {
269
if (event.type === "transform_failed") {
270
handleTransformError(event.error, event.context);
271
}
272
},
273
},
274
};
275
```
276
277
### Common Solutions
278
279
#### Fixing Invalid Require Calls
280
281
```javascript
282
// Before: Dynamic require (will fail)
283
const moduleName = getModuleName();
284
require(moduleName);
285
286
// After: Static require with conditional logic
287
const moduleA = require("module-a");
288
const moduleB = require("module-b");
289
const selectedModule = condition ? moduleA : moduleB;
290
```
291
292
#### Resolving Reserved String Conflicts
293
294
```javascript
295
// Before: Code contains reserved string
296
const _$$_METRO_MODULE_ID = "my-id"; // Will fail
297
298
// After: Use different variable name
299
const MY_MODULE_ID = "my-id"; // Will succeed
300
```
301
302
#### Handling Minification Issues
303
304
```javascript
305
// Before: Syntax that confuses minifier
306
eval("some code"); // May fail minification
307
308
// After: Avoid problematic constructs
309
const result = safeEvalAlternative("some code");
310
```