vercel-labs/skills · error · GitCloneError
Failed to clone ${url}: ${errorMessage}
Error message
Failed to clone ${url}: ${errorMessage} What it means
The generic clone failure in cloneRepo(): git exited non-zero, it was neither a timeout nor an auth error, so the raw git stderr is wrapped: 'Failed to clone <url>: <message>'. The temp directory is cleaned up before throwing.
Source
Thrown at src/git.ts:297
await resetTempDir(tempDir);
await createGitClient(process.env.GIT_SSH_COMMAND ?? 'ssh -o BatchMode=yes').clone(
repo.sshUrl,
tempDir,
cloneOptions
);
return tempDir;
} catch {
// Fall through to the targeted auth error below.
}
}
await rm(tempDir, { recursive: true, force: true }).catch(() => {});
if (isAuthError) {
throw new GitCloneError(buildGitHubAuthError(url, repo, errorMessage), url, false, true);
}
throw new GitCloneError(`Failed to clone ${url}: ${errorMessage}`, url, false, false);
}
}
/**
* Resolve the Git tree object for a locked skill path in a cloned repository.
* This matches the folder SHA returned by GitHub's Trees API.
*/
export async function getGitTreeHash(repoDir: string, skillPath: string): Promise<string | null> {
const normalizedPath = skillPath.replace(/\\/g, '/');
const segments = normalizedPath.split('/');
segments.pop();
const folderPath = segments.join('/');
const revision = folderPath ? `HEAD:${folderPath}` : 'HEAD^{tree}';
try {
const stdout = await new Promise<string>((resolve, reject) => {
execFile(
'git',View on GitHub (pinned to 435076e789)
Solutions
- Copy the git stderr from the message and reproduce manually: git clone --depth 1 <url> to see the full failure
- Fix the URL/branch: verify the repo exists in a browser and the branch name is correct
- If DNS/proxy: configure https.proxy or correct corporate proxy env vars
- If repo is private, see auth errors — sometimes 404 masks missing credentials
Example fix
# before (branch typo) skills add github.com/org/repo --ref maain # after skills add github.com/org/repo --ref main
Defensive patterns
Strategy: try-catch
Validate before calling
const exists = await fetch(`https://api.github.com/repos/${owner}/${repo}`, {
headers: token ? { Authorization: `Bearer ${token}` } : {},
}).then((r) => r.ok);
if (!exists) throw new Error(`Repo ${owner}/${repo} not reachable; check spelling/visibility`); Type guard
function isGitCloneError(e: unknown): e is Error {
return e instanceof Error && /^Failed to clone /.test(e.message);
} Try / catch
try { await cloneRepo(url, ref); }
catch (e) {
if (isGitCloneError(e)) {
logger.error(e.message); // contains raw git stderr for diagnosis
return fallbackToLocalMirror(url);
}
throw e;
} Prevention
- Validate owner/repo spelling and branch names before cloning
- Reproduce failures manually with git clone --depth 1
- Wrap cloneRepo and surface the embedded git stderr to users
When it happens
Trigger: Any non-timeout, non-auth git failure: repository not found (HTTPS 404 on public repo), invalid ref/branch name, malformed URL, DNS failure ('Could not resolve host'), disk full, or unsupported git protocol.
Common situations: Typos in owner/repo shorthand; deleted or renamed repositories; branch specified doesn't exist; corporate proxies blocking git:// protocol; old git versions lacking needed features.
Related errors
- Clone timed out after ${seconds}s. Common causes: - Large
- Unsupported Git transport: ext
- buildGitHubAuthError(url, repo, errorMessage)
AI-assisted analysis of vercel-labs/skills@435076e789 (2026-08-28).
Data as JSON: /api/errors/bbcdab24392f5ca7.
Report an issue: GitHub.