or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asset-resolution.mdcustom-resolvers.mderror-handling.mdindex.mdpackage-resolution.mdresolution-context.mdresolution-engine.md

error-handling.mddocs/

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

```