A pure JavaScript implementation of git for node and browsers
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
isomorphic-git provides a comprehensive set of error classes for different failure conditions.
/**
* Base error class for all isomorphic-git errors
*/
class BaseError extends Error {
name: string;
code: string;
data: any;
}
/**
* Reference or object not found
*/
class NotFoundError extends BaseError {
constructor(what: string);
}
/**
* Invalid reference name
*/
class InvalidRefNameError extends BaseError {
constructor(ref: string);
}
/**
* Invalid object ID format
*/
class InvalidOidError extends BaseError {
constructor(value: string);
}
/**
* Invalid file path
*/
class InvalidFilepathError extends BaseError {
constructor(filepath: string);
}
/**
* Unsafe file path (potential security issue)
*/
class UnsafeFilepathError extends BaseError {
constructor(filepath: string);
}
/**
* Required parameter missing
*/
class MissingParameterError extends BaseError {
constructor(parameter: string);
}
/**
* Required name parameter missing
*/
class MissingNameError extends BaseError {
constructor();
}
/**
* Ambiguous reference (multiple matches)
*/
class AmbiguousError extends BaseError {
constructor(nouns: string[], matches: string[]);
}
/**
* Object or reference already exists
*/
class AlreadyExistsError extends BaseError {
constructor(noun: string, where: string, name?: string);
}
/**
* Internal library error
*/
class InternalError extends BaseError {
constructor(message: string);
}/**
* Checkout would overwrite local changes
*/
class CheckoutConflictError extends BaseError {
constructor(filepaths: string[]);
}
/**
* Merge conflict occurred
*/
class MergeConflictError extends BaseError {
constructor(filepaths: string[]);
}
/**
* Merge operation not supported for this scenario
*/
class MergeNotSupportedError extends BaseError {
constructor();
}
/**
* Repository has unmerged paths
*/
class UnmergedPathsError extends BaseError {
constructor(filepaths: string[]);
}
/**
* Fast-forward merge not possible
*/
class FastForwardError extends BaseError {
constructor();
}/**
* HTTP request error
*/
class HttpError extends BaseError {
constructor(statusCode: number, statusMessage: string, response: string);
}
/**
* Git push operation failed
*/
class GitPushError extends BaseError {
constructor(prettyDetails: string, result: any);
}
/**
* Push rejected by remote server
*/
class PushRejectedError extends BaseError {
constructor(reason: string);
}
/**
* Empty response from server
*/
class EmptyServerResponseError extends BaseError {
constructor();
}
/**
* Smart HTTP protocol error
*/
class SmartHttpError extends BaseError {
constructor(preview: string, response: string);
}
/**
* Remote capability not supported
*/
class RemoteCapabilityError extends BaseError {
constructor(capability: string, remote: string);
}
/**
* Unknown transport protocol
*/
class UnknownTransportError extends BaseError {
constructor(url: string);
}
/**
* URL parsing error
*/
class UrlParseError extends BaseError {
constructor(url: string);
}
/**
* No refspec configured for push/pull
*/
class NoRefspecError extends BaseError {
constructor(remote: string);
}/**
* Required commit not fetched from remote
*/
class CommitNotFetchedError extends BaseError {
constructor(ref: string, oid: string);
}
/**
* No commit found (empty repository)
*/
class NoCommitError extends BaseError {
constructor();
}
/**
* Multiple .git directories found
*/
class MultipleGitError extends BaseError {
constructor(gitdirs: string[]);
}
/**
* Maximum recursion depth reached
*/
class MaxDepthError extends BaseError {
constructor(depth: number);
}
/**
* Object type mismatch
*/
class ObjectTypeError extends BaseError {
constructor(oid: string, actual: string, expected: string);
}
/**
* Parsing error for Git objects or references
*/
class ParseError extends BaseError {
constructor(expected: string, actual: string);
}
/**
* Index reset error
*/
class IndexResetError extends BaseError {
constructor(filepath: string);
}/**
* User canceled the operation
*/
class UserCanceledError extends BaseError {
constructor();
}import git, { Errors } from "isomorphic-git";
import fs from "fs";
try {
await git.checkout({
fs,
dir: "/path/to/repo",
ref: "nonexistent-branch"
});
} catch (error) {
if (error instanceof Errors.NotFoundError) {
console.log("Branch not found:", error.data);
} else {
console.log("Unexpected error:", error.message);
}
}import git, { Errors } from "isomorphic-git";
import fs from "fs";
try {
await git.checkout({
fs,
dir: "/path/to/repo",
ref: "main"
});
} catch (error) {
switch (error.constructor) {
case Errors.CheckoutConflictError:
console.log("Cannot checkout - would overwrite:", error.data.filepaths);
// Offer to stash or commit changes
break;
case Errors.NotFoundError:
console.log("Branch not found:", error.data);
// Offer to create branch or list available branches
break;
case Errors.InvalidRefNameError:
console.log("Invalid branch name:", error.data.ref);
break;
default:
console.log("Checkout failed:", error.message);
}
}import git, { Errors } from "isomorphic-git";
import http from "isomorphic-git/http/node";
import fs from "fs";
try {
await git.push({
fs,
http,
dir: "/path/to/repo",
remote: "origin",
ref: "main"
});
} catch (error) {
if (error instanceof Errors.HttpError) {
switch (error.data.statusCode) {
case 401:
console.log("Authentication required");
break;
case 403:
console.log("Permission denied");
break;
case 404:
console.log("Repository not found");
break;
default:
console.log(`HTTP error ${error.data.statusCode}: ${error.data.statusMessage}`);
}
} else if (error instanceof Errors.PushRejectedError) {
console.log("Push rejected:", error.data.reason);
console.log("Try pulling latest changes first");
} else if (error instanceof Errors.GitPushError) {
console.log("Push failed:", error.data.prettyDetails);
} else {
console.log("Push error:", error.message);
}
}import git, { Errors } from "isomorphic-git";
import fs from "fs";
try {
const result = await git.merge({
fs,
dir: "/path/to/repo",
theirs: "feature-branch"
});
if (result.conflicts && result.conflicts.length > 0) {
console.log("Merge conflicts in:", result.conflicts);
console.log("Please resolve conflicts and commit");
} else {
console.log("Merge completed successfully");
}
} catch (error) {
if (error instanceof Errors.MergeConflictError) {
console.log("Merge conflicts detected in:", error.data.filepaths);
console.log("Resolve conflicts manually, then:");
console.log("1. git add <resolved-files>");
console.log("2. git commit");
} else if (error instanceof Errors.MergeNotSupportedError) {
console.log("This type of merge is not supported");
console.log("Try a different merge strategy");
} else {
console.log("Merge failed:", error.message);
}
}import git, { Errors } from "isomorphic-git";
import http from "isomorphic-git/http/node";
import fs from "fs";
try {
await git.clone({
fs,
http,
dir: "/path/to/repo",
url: "https://github.com/user/repo.git"
});
} catch (error) {
if (error instanceof Errors.HttpError) {
if (error.data.statusCode === 404) {
console.log("Repository not found or private");
} else {
console.log(`Network error: ${error.data.statusCode}`);
}
} else if (error instanceof Errors.AlreadyExistsError) {
console.log("Directory already exists and is not empty");
} else if (error instanceof Errors.UrlParseError) {
console.log("Invalid repository URL:", error.data.url);
} else {
console.log("Clone failed:", error.message);
}
}import git, { Errors } from "isomorphic-git";
import fs from "fs";
try {
const userName = await git.getConfig({
fs,
dir: "/path/to/repo",
path: "user.name"
});
console.log("User name:", userName);
} catch (error) {
if (error instanceof Errors.NotFoundError) {
console.log("Configuration not found - setting default");
await git.setConfig({
fs,
dir: "/path/to/repo",
path: "user.name",
value: "Default User"
});
} else {
console.log("Configuration error:", error.message);
}
}import git, { Errors } from "isomorphic-git";
import fs from "fs";
try {
await git.add({
fs,
dir: "/path/to/repo",
filepath: "nonexistent/file.txt"
});
} catch (error) {
if (error instanceof Errors.NotFoundError) {
console.log("File not found:", error.data);
} else if (error instanceof Errors.InvalidFilepathError) {
console.log("Invalid file path:", error.data.filepath);
} else if (error instanceof Errors.UnsafeFilepathError) {
console.log("Unsafe file path detected:", error.data.filepath);
} else {
console.log("Add failed:", error.message);
}
}Most errors include additional data in the data property:
import git, { Errors } from "isomorphic-git";
import fs from "fs";
try {
// Some operation that fails
await git.resolveRef({
fs,
dir: "/path/to/repo",
ref: "ambiguous-ref"
});
} catch (error) {
console.log("Error name:", error.name);
console.log("Error code:", error.code);
console.log("Error message:", error.message);
console.log("Error data:", error.data);
console.log("Stack trace:", error.stack);
}// Good: Handle expected error conditions
try {
await git.checkout({ fs, dir, ref: userInput });
} catch (error) {
if (error instanceof Errors.NotFoundError) {
// Handle missing branch gracefully
console.log(`Branch '${userInput}' not found`);
return;
}
throw error; // Re-throw unexpected errors
}// Good: Convert technical errors to user-friendly messages
try {
await git.push({ fs, http, dir, remote: "origin", ref: "main" });
} catch (error) {
let userMessage;
if (error instanceof Errors.HttpError && error.data.statusCode === 401) {
userMessage = "Authentication failed. Please check your credentials.";
} else if (error instanceof Errors.PushRejectedError) {
userMessage = "Push rejected. Please pull the latest changes first.";
} else {
userMessage = `Push failed: ${error.message}`;
}
console.log(userMessage);
}// Good: Log technical details for debugging
try {
await someGitOperation();
} catch (error) {
// User-friendly message
console.log("Operation failed:", getUserFriendlyMessage(error));
// Technical details for logs
console.error("Technical details:", {
error: error.name,
code: error.code,
data: error.data,
stack: error.stack
});
}