0
# Error Handling
1
2
isomorphic-git provides a comprehensive set of error classes for different failure conditions.
3
4
## Error Classes
5
6
### Core Errors
7
8
```javascript { .api }
9
/**
10
* Base error class for all isomorphic-git errors
11
*/
12
class BaseError extends Error {
13
name: string;
14
code: string;
15
data: any;
16
}
17
18
/**
19
* Reference or object not found
20
*/
21
class NotFoundError extends BaseError {
22
constructor(what: string);
23
}
24
25
/**
26
* Invalid reference name
27
*/
28
class InvalidRefNameError extends BaseError {
29
constructor(ref: string);
30
}
31
32
/**
33
* Invalid object ID format
34
*/
35
class InvalidOidError extends BaseError {
36
constructor(value: string);
37
}
38
39
/**
40
* Invalid file path
41
*/
42
class InvalidFilepathError extends BaseError {
43
constructor(filepath: string);
44
}
45
46
/**
47
* Unsafe file path (potential security issue)
48
*/
49
class UnsafeFilepathError extends BaseError {
50
constructor(filepath: string);
51
}
52
53
/**
54
* Required parameter missing
55
*/
56
class MissingParameterError extends BaseError {
57
constructor(parameter: string);
58
}
59
60
/**
61
* Required name parameter missing
62
*/
63
class MissingNameError extends BaseError {
64
constructor();
65
}
66
67
/**
68
* Ambiguous reference (multiple matches)
69
*/
70
class AmbiguousError extends BaseError {
71
constructor(nouns: string[], matches: string[]);
72
}
73
74
/**
75
* Object or reference already exists
76
*/
77
class AlreadyExistsError extends BaseError {
78
constructor(noun: string, where: string, name?: string);
79
}
80
81
/**
82
* Internal library error
83
*/
84
class InternalError extends BaseError {
85
constructor(message: string);
86
}
87
```
88
89
### Checkout and Merge Errors
90
91
```javascript { .api }
92
/**
93
* Checkout would overwrite local changes
94
*/
95
class CheckoutConflictError extends BaseError {
96
constructor(filepaths: string[]);
97
}
98
99
/**
100
* Merge conflict occurred
101
*/
102
class MergeConflictError extends BaseError {
103
constructor(filepaths: string[]);
104
}
105
106
/**
107
* Merge operation not supported for this scenario
108
*/
109
class MergeNotSupportedError extends BaseError {
110
constructor();
111
}
112
113
/**
114
* Repository has unmerged paths
115
*/
116
class UnmergedPathsError extends BaseError {
117
constructor(filepaths: string[]);
118
}
119
120
/**
121
* Fast-forward merge not possible
122
*/
123
class FastForwardError extends BaseError {
124
constructor();
125
}
126
```
127
128
### Remote Operation Errors
129
130
```javascript { .api }
131
/**
132
* HTTP request error
133
*/
134
class HttpError extends BaseError {
135
constructor(statusCode: number, statusMessage: string, response: string);
136
}
137
138
/**
139
* Git push operation failed
140
*/
141
class GitPushError extends BaseError {
142
constructor(prettyDetails: string, result: any);
143
}
144
145
/**
146
* Push rejected by remote server
147
*/
148
class PushRejectedError extends BaseError {
149
constructor(reason: string);
150
}
151
152
/**
153
* Empty response from server
154
*/
155
class EmptyServerResponseError extends BaseError {
156
constructor();
157
}
158
159
/**
160
* Smart HTTP protocol error
161
*/
162
class SmartHttpError extends BaseError {
163
constructor(preview: string, response: string);
164
}
165
166
/**
167
* Remote capability not supported
168
*/
169
class RemoteCapabilityError extends BaseError {
170
constructor(capability: string, remote: string);
171
}
172
173
/**
174
* Unknown transport protocol
175
*/
176
class UnknownTransportError extends BaseError {
177
constructor(url: string);
178
}
179
180
/**
181
* URL parsing error
182
*/
183
class UrlParseError extends BaseError {
184
constructor(url: string);
185
}
186
187
/**
188
* No refspec configured for push/pull
189
*/
190
class NoRefspecError extends BaseError {
191
constructor(remote: string);
192
}
193
```
194
195
### Repository State Errors
196
197
```javascript { .api }
198
/**
199
* Required commit not fetched from remote
200
*/
201
class CommitNotFetchedError extends BaseError {
202
constructor(ref: string, oid: string);
203
}
204
205
/**
206
* No commit found (empty repository)
207
*/
208
class NoCommitError extends BaseError {
209
constructor();
210
}
211
212
/**
213
* Multiple .git directories found
214
*/
215
class MultipleGitError extends BaseError {
216
constructor(gitdirs: string[]);
217
}
218
219
/**
220
* Maximum recursion depth reached
221
*/
222
class MaxDepthError extends BaseError {
223
constructor(depth: number);
224
}
225
226
/**
227
* Object type mismatch
228
*/
229
class ObjectTypeError extends BaseError {
230
constructor(oid: string, actual: string, expected: string);
231
}
232
233
/**
234
* Parsing error for Git objects or references
235
*/
236
class ParseError extends BaseError {
237
constructor(expected: string, actual: string);
238
}
239
240
/**
241
* Index reset error
242
*/
243
class IndexResetError extends BaseError {
244
constructor(filepath: string);
245
}
246
```
247
248
### User Interaction Errors
249
250
```javascript { .api }
251
/**
252
* User canceled the operation
253
*/
254
class UserCanceledError extends BaseError {
255
constructor();
256
}
257
```
258
259
## Usage Examples
260
261
### Basic Error Handling
262
263
```javascript
264
import git, { Errors } from "isomorphic-git";
265
import fs from "fs";
266
267
try {
268
await git.checkout({
269
fs,
270
dir: "/path/to/repo",
271
ref: "nonexistent-branch"
272
});
273
} catch (error) {
274
if (error instanceof Errors.NotFoundError) {
275
console.log("Branch not found:", error.data);
276
} else {
277
console.log("Unexpected error:", error.message);
278
}
279
}
280
```
281
282
### Specific Error Handling
283
284
```javascript
285
import git, { Errors } from "isomorphic-git";
286
import fs from "fs";
287
288
try {
289
await git.checkout({
290
fs,
291
dir: "/path/to/repo",
292
ref: "main"
293
});
294
} catch (error) {
295
switch (error.constructor) {
296
case Errors.CheckoutConflictError:
297
console.log("Cannot checkout - would overwrite:", error.data.filepaths);
298
// Offer to stash or commit changes
299
break;
300
301
case Errors.NotFoundError:
302
console.log("Branch not found:", error.data);
303
// Offer to create branch or list available branches
304
break;
305
306
case Errors.InvalidRefNameError:
307
console.log("Invalid branch name:", error.data.ref);
308
break;
309
310
default:
311
console.log("Checkout failed:", error.message);
312
}
313
}
314
```
315
316
### Network Error Handling
317
318
```javascript
319
import git, { Errors } from "isomorphic-git";
320
import http from "isomorphic-git/http/node";
321
import fs from "fs";
322
323
try {
324
await git.push({
325
fs,
326
http,
327
dir: "/path/to/repo",
328
remote: "origin",
329
ref: "main"
330
});
331
} catch (error) {
332
if (error instanceof Errors.HttpError) {
333
switch (error.data.statusCode) {
334
case 401:
335
console.log("Authentication required");
336
break;
337
case 403:
338
console.log("Permission denied");
339
break;
340
case 404:
341
console.log("Repository not found");
342
break;
343
default:
344
console.log(`HTTP error ${error.data.statusCode}: ${error.data.statusMessage}`);
345
}
346
} else if (error instanceof Errors.PushRejectedError) {
347
console.log("Push rejected:", error.data.reason);
348
console.log("Try pulling latest changes first");
349
} else if (error instanceof Errors.GitPushError) {
350
console.log("Push failed:", error.data.prettyDetails);
351
} else {
352
console.log("Push error:", error.message);
353
}
354
}
355
```
356
357
### Merge Conflict Handling
358
359
```javascript
360
import git, { Errors } from "isomorphic-git";
361
import fs from "fs";
362
363
try {
364
const result = await git.merge({
365
fs,
366
dir: "/path/to/repo",
367
theirs: "feature-branch"
368
});
369
370
if (result.conflicts && result.conflicts.length > 0) {
371
console.log("Merge conflicts in:", result.conflicts);
372
console.log("Please resolve conflicts and commit");
373
} else {
374
console.log("Merge completed successfully");
375
}
376
} catch (error) {
377
if (error instanceof Errors.MergeConflictError) {
378
console.log("Merge conflicts detected in:", error.data.filepaths);
379
console.log("Resolve conflicts manually, then:");
380
console.log("1. git add <resolved-files>");
381
console.log("2. git commit");
382
} else if (error instanceof Errors.MergeNotSupportedError) {
383
console.log("This type of merge is not supported");
384
console.log("Try a different merge strategy");
385
} else {
386
console.log("Merge failed:", error.message);
387
}
388
}
389
```
390
391
### Clone Error Handling
392
393
```javascript
394
import git, { Errors } from "isomorphic-git";
395
import http from "isomorphic-git/http/node";
396
import fs from "fs";
397
398
try {
399
await git.clone({
400
fs,
401
http,
402
dir: "/path/to/repo",
403
url: "https://github.com/user/repo.git"
404
});
405
} catch (error) {
406
if (error instanceof Errors.HttpError) {
407
if (error.data.statusCode === 404) {
408
console.log("Repository not found or private");
409
} else {
410
console.log(`Network error: ${error.data.statusCode}`);
411
}
412
} else if (error instanceof Errors.AlreadyExistsError) {
413
console.log("Directory already exists and is not empty");
414
} else if (error instanceof Errors.UrlParseError) {
415
console.log("Invalid repository URL:", error.data.url);
416
} else {
417
console.log("Clone failed:", error.message);
418
}
419
}
420
```
421
422
### Configuration Error Handling
423
424
```javascript
425
import git, { Errors } from "isomorphic-git";
426
import fs from "fs";
427
428
try {
429
const userName = await git.getConfig({
430
fs,
431
dir: "/path/to/repo",
432
path: "user.name"
433
});
434
console.log("User name:", userName);
435
} catch (error) {
436
if (error instanceof Errors.NotFoundError) {
437
console.log("Configuration not found - setting default");
438
await git.setConfig({
439
fs,
440
dir: "/path/to/repo",
441
path: "user.name",
442
value: "Default User"
443
});
444
} else {
445
console.log("Configuration error:", error.message);
446
}
447
}
448
```
449
450
### File System Error Handling
451
452
```javascript
453
import git, { Errors } from "isomorphic-git";
454
import fs from "fs";
455
456
try {
457
await git.add({
458
fs,
459
dir: "/path/to/repo",
460
filepath: "nonexistent/file.txt"
461
});
462
} catch (error) {
463
if (error instanceof Errors.NotFoundError) {
464
console.log("File not found:", error.data);
465
} else if (error instanceof Errors.InvalidFilepathError) {
466
console.log("Invalid file path:", error.data.filepath);
467
} else if (error instanceof Errors.UnsafeFilepathError) {
468
console.log("Unsafe file path detected:", error.data.filepath);
469
} else {
470
console.log("Add failed:", error.message);
471
}
472
}
473
```
474
475
## Error Information
476
477
Most errors include additional data in the `data` property:
478
479
```javascript
480
import git, { Errors } from "isomorphic-git";
481
import fs from "fs";
482
483
try {
484
// Some operation that fails
485
await git.resolveRef({
486
fs,
487
dir: "/path/to/repo",
488
ref: "ambiguous-ref"
489
});
490
} catch (error) {
491
console.log("Error name:", error.name);
492
console.log("Error code:", error.code);
493
console.log("Error message:", error.message);
494
console.log("Error data:", error.data);
495
console.log("Stack trace:", error.stack);
496
}
497
```
498
499
## Best Practices
500
501
### 1. Always Handle Expected Errors
502
503
```javascript
504
// Good: Handle expected error conditions
505
try {
506
await git.checkout({ fs, dir, ref: userInput });
507
} catch (error) {
508
if (error instanceof Errors.NotFoundError) {
509
// Handle missing branch gracefully
510
console.log(`Branch '${userInput}' not found`);
511
return;
512
}
513
throw error; // Re-throw unexpected errors
514
}
515
```
516
517
### 2. Provide User-Friendly Messages
518
519
```javascript
520
// Good: Convert technical errors to user-friendly messages
521
try {
522
await git.push({ fs, http, dir, remote: "origin", ref: "main" });
523
} catch (error) {
524
let userMessage;
525
526
if (error instanceof Errors.HttpError && error.data.statusCode === 401) {
527
userMessage = "Authentication failed. Please check your credentials.";
528
} else if (error instanceof Errors.PushRejectedError) {
529
userMessage = "Push rejected. Please pull the latest changes first.";
530
} else {
531
userMessage = `Push failed: ${error.message}`;
532
}
533
534
console.log(userMessage);
535
}
536
```
537
538
### 3. Log Detailed Error Information
539
540
```javascript
541
// Good: Log technical details for debugging
542
try {
543
await someGitOperation();
544
} catch (error) {
545
// User-friendly message
546
console.log("Operation failed:", getUserFriendlyMessage(error));
547
548
// Technical details for logs
549
console.error("Technical details:", {
550
error: error.name,
551
code: error.code,
552
data: error.data,
553
stack: error.stack
554
});
555
}
556
```