or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cache-management.mderror-handling.mdfile-map-core.mdfile-system.mdhaste-system.mdindex.mdplugin-system.md

error-handling.mddocs/

0

# Error Handling

1

2

Specialized error classes for Haste conflicts, duplicate candidates, and other metro-file-map specific error conditions. These errors provide detailed information for debugging module resolution and file system issues.

3

4

## Capabilities

5

6

### HasteConflictsError

7

8

Error thrown when Haste module naming conflicts are detected and strict validation is enabled.

9

10

```javascript { .api }

11

/**

12

* Error for Haste module conflicts

13

*/

14

class HasteConflictsError extends Error {

15

/**

16

* Create error with conflict details

17

* @param conflicts - Array of detected conflicts

18

*/

19

constructor(conflicts: ReadonlyArray<HasteConflict>);

20

21

/**

22

* Get detailed error message with conflict information

23

* @param pathsRelativeToRoot - Optional root path for relative paths in output

24

* @returns Detailed error message string

25

*/

26

getDetailedMessage(pathsRelativeToRoot?: string): string;

27

}

28

```

29

30

**Usage Examples:**

31

32

```javascript

33

import { HasteConflictsError } from "metro-file-map";

34

35

try {

36

// This will throw if conflicts detected and throwOnModuleCollision: true

37

const fileMap = new FileMap({

38

// ... options

39

throwOnModuleCollision: true

40

});

41

42

await fileMap.build();

43

} catch (error) {

44

if (error instanceof HasteConflictsError) {

45

console.error('Haste conflicts detected:');

46

console.error(error.getDetailedMessage(process.cwd()));

47

48

// Example output:

49

// Haste conflicts detected:

50

//

51

// Duplicate module name "Button" found:

52

// - src/components/Button.js

53

// - src/ui/Button.js

54

//

55

// Module "Header" has platform conflicts:

56

// - Platform "ios": src/Header.ios.js

57

// - Platform "ios": lib/Header.ios.js (shadows src/Header.js)

58

} else {

59

throw error;

60

}

61

}

62

```

63

64

### DuplicateHasteCandidatesError

65

66

Error thrown when multiple files declare the same Haste module name for a specific platform.

67

68

```javascript { .api }

69

/**

70

* Error for duplicate Haste module candidates

71

*/

72

class DuplicateHasteCandidatesError extends Error {

73

/**

74

* Create error for duplicate module candidates

75

* @param name - Module name with duplicates

76

* @param platform - Platform where duplicates exist

77

* @param supportsNativePlatform - Whether native platform is supported

78

* @param duplicatesSet - Set of duplicate file information

79

*/

80

constructor(

81

name: string,

82

platform: string,

83

supportsNativePlatform: boolean,

84

duplicatesSet: DuplicatesSet

85

);

86

}

87

```

88

89

**Usage Examples:**

90

91

```javascript

92

import { DuplicateHasteCandidatesError } from "metro-file-map";

93

94

try {

95

// Attempt to resolve module that has duplicates

96

const modulePath = hasteMap.getModule('Button', 'ios');

97

} catch (error) {

98

if (error instanceof DuplicateHasteCandidatesError) {

99

console.error(`Multiple files found for module "${error.name}" on platform "${error.platform}"`);

100

101

// Handle the duplicate by choosing one or prompting user

102

const alternatives = Array.from(error.duplicatesSet.keys());

103

console.log('Available options:');

104

alternatives.forEach((path, index) => {

105

console.log(` ${index + 1}. ${path}`);

106

});

107

}

108

}

109

```

110

111

### Error Context and Debugging

112

113

Errors provide rich context for debugging file system and module resolution issues.

114

115

```javascript { .api }

116

/**

117

* Conflict information included in errors

118

*/

119

interface HasteConflict {

120

/** Module name with conflict */

121

id: string;

122

/** Platform where conflict occurs (null for all platforms) */

123

platform: string | null;

124

/** Absolute paths of conflicting files */

125

absolutePaths: Array<string>;

126

/** Type of conflict */

127

type: 'duplicate' | 'shadowing';

128

}

129

130

/**

131

* Duplicate candidates information

132

*/

133

type DuplicatesSet = Map<string, number>;

134

```

135

136

**Usage Examples:**

137

138

```javascript

139

// Comprehensive error handling for FileMap operations

140

async function buildFileMapSafely(options) {

141

try {

142

const fileMap = new FileMap(options);

143

const result = await fileMap.build();

144

145

// Check for conflicts even if not throwing

146

const conflicts = result.hasteMap.computeConflicts();

147

if (conflicts.length > 0) {

148

console.warn(`Warning: ${conflicts.length} Haste conflicts detected`);

149

conflicts.forEach(conflict => {

150

console.warn(` ${conflict.type}: ${conflict.id} (${conflict.platform || 'all platforms'})`);

151

conflict.absolutePaths.forEach(path => {

152

console.warn(` - ${path}`);

153

});

154

});

155

}

156

157

return result;

158

} catch (error) {

159

if (error instanceof HasteConflictsError) {

160

console.error('❌ Haste module conflicts:');

161

console.error(error.getDetailedMessage());

162

process.exit(1);

163

} else if (error instanceof DuplicateHasteCandidatesError) {

164

console.error('❌ Duplicate module candidates detected');

165

console.error(error.message);

166

process.exit(1);

167

} else {

168

console.error('❌ Unexpected error during file mapping:');

169

console.error(error);

170

throw error;

171

}

172

}

173

}

174

175

// Usage

176

const result = await buildFileMapSafely({

177

extensions: ['.js', '.ts'],

178

platforms: ['ios', 'android'],

179

retainAllFiles: false,

180

rootDir: process.cwd(),

181

roots: ['./src'],

182

maxWorkers: 4,

183

healthCheck: { enabled: false, interval: 30000, timeout: 5000, filePrefix: 'test' },

184

throwOnModuleCollision: true

185

});

186

```

187

188

### Conflict Resolution Strategies

189

190

Handle conflicts programmatically based on error information.

191

192

**Usage Examples:**

193

194

```javascript

195

// Automatic conflict resolution

196

class ConflictResolver {

197

static resolveHasteConflicts(conflicts) {

198

const resolutions = new Map();

199

200

conflicts.forEach(conflict => {

201

switch (conflict.type) {

202

case 'duplicate':

203

// Choose file with shortest path (closest to root)

204

const shortestPath = conflict.absolutePaths.reduce((shortest, current) =>

205

current.length < shortest.length ? current : shortest

206

);

207

resolutions.set(conflict.id, shortestPath);

208

console.log(`Resolved duplicate "${conflict.id}" -> ${shortestPath}`);

209

break;

210

211

case 'shadowing':

212

// Prefer platform-specific over generic

213

const platformSpecific = conflict.absolutePaths.find(path =>

214

path.includes(`.${conflict.platform}.`)

215

);

216

if (platformSpecific) {

217

resolutions.set(conflict.id, platformSpecific);

218

console.log(`Resolved shadowing "${conflict.id}" -> ${platformSpecific}`);

219

}

220

break;

221

}

222

});

223

224

return resolutions;

225

}

226

227

static async buildWithConflictResolution(options) {

228

try {

229

return await buildFileMapSafely({ ...options, throwOnModuleCollision: true });

230

} catch (error) {

231

if (error instanceof HasteConflictsError) {

232

console.log('Attempting automatic conflict resolution...');

233

234

const resolutions = this.resolveHasteConflicts(error.conflicts);

235

236

// Retry with conflict resolution (implementation would need custom plugin)

237

return await buildFileMapSafely({

238

...options,

239

throwOnModuleCollision: false,

240

conflictResolutions: resolutions

241

});

242

}

243

throw error;

244

}

245

}

246

}

247

```

248

249

### Error Prevention

250

251

Strategies for preventing common errors through configuration.

252

253

**Usage Examples:**

254

255

```javascript

256

// Configuration to prevent common errors

257

const robustFileMapOptions = {

258

extensions: ['.js', '.jsx', '.ts', '.tsx'],

259

platforms: ['ios', 'android', 'native', 'web'],

260

retainAllFiles: false,

261

rootDir: process.cwd(),

262

roots: ['./src'],

263

maxWorkers: require('os').cpus().length,

264

healthCheck: { enabled: false, interval: 30000, timeout: 5000, filePrefix: 'test' },

265

266

// Error prevention settings

267

throwOnModuleCollision: false, // Don't throw on conflicts

268

ignorePattern: /node_modules|\.git/, // Ignore problematic directories

269

enableHastePackages: false, // Disable if causing conflicts

270

271

// Custom conflict-aware plugin

272

plugins: [

273

new ConflictAwareHastePlugin({

274

enableHastePackages: false,

275

platforms: new Set(['ios', 'android', 'native', 'web']),

276

rootDir: process.cwd(),

277

failValidationOnConflicts: false,

278

autoResolveConflicts: true

279

})

280

]

281

};

282

283

// Build with error recovery

284

async function buildWithRetry(options, maxRetries = 3) {

285

for (let attempt = 1; attempt <= maxRetries; attempt++) {

286

try {

287

return await buildFileMapSafely(options);

288

} catch (error) {

289

console.log(`Attempt ${attempt}/${maxRetries} failed:`, error.message);

290

291

if (attempt === maxRetries) {

292

console.error('All retry attempts failed');

293

throw error;

294

}

295

296

// Modify options for retry (e.g., disable features causing errors)

297

if (error instanceof HasteConflictsError) {

298

options.throwOnModuleCollision = false;

299

options.enableHastePackages = false;

300

}

301

}

302

}

303

}

304

```

305

306

## Types

307

308

```javascript { .api }

309

interface HasteConflict {

310

id: string;

311

platform: string | null;

312

absolutePaths: Array<string>;

313

type: 'duplicate' | 'shadowing';

314

}

315

316

type DuplicatesSet = Map<string, number>;

317

318

type DuplicatesIndex = Map<string, Map<string, DuplicatesSet>>;

319

320

interface ErrorWithConflicts extends Error {

321

conflicts: ReadonlyArray<HasteConflict>;

322

}

323

```