vercel-labs/skills · error · GitCloneError

buildGitHubAuthError(url, repo, errorMessage)

Error message

buildGitHubAuthError(url, repo, errorMessage)

What it means

When a clone fails and the error text matches auth-failure heuristics (isAuthFailure), cloneRepo throws a GitCloneError whose message is built by buildGitHubAuthError — a detailed guide covering SSH key and HTTPS/gh credential setup for private repositories.

Source

Thrown at src/git.ts:294

      }

      try {
        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 {

View on GitHub (pinned to 435076e789)

Solutions

  1. For HTTPS: run gh auth login (or export GH_TOKEN/GITHUB_TOKEN with repo scope)
  2. For SSH: verify ssh-add -l lists a key and ssh -T git@github.com authenticates
  3. If using a PAT, confirm it is not expired and has access to the specific private org/repo (SSO authorized)
  4. Alternatively clone where credentials already work and 'skills add <local-path>'

Example fix

# before
skills add github.com/org/private-skills   # auth failure
# after
gh auth login
skills add github.com/org/private-skills
Defensive patterns

Strategy: fallback

Validate before calling

async function canClone(url: string): Promise<boolean> {
  try {
    execSync(`git ls-remote ${JSON.stringify(url)} HEAD`, { stdio: 'ignore', timeout: 20000 });
    return true;
  } catch { return false; }
}

Type guard

function isGitAuthError(e: unknown): e is Error {
  return e instanceof Error && /Permission to|authentication|credentials|gh auth|publickey/i.test(e.message);
}

Try / catch

try { await cloneRepo(url); }
catch (e) {
  if (isGitAuthError(e)) {
    notifyUser('Run `gh auth login` or load an SSH key, then retry');
    return; // user-actionable, don't crash the process
  }
  throw e;
}

Prevention

When it happens

Trigger: Cloning a private GitHub repo with missing/invalid credentials: no SSH key loaded (Permission denied (publickey)), expired gh token, revoked PAT, or HTTPS 403/Authentication failed output from git.

Common situations: Fresh machines without gh auth login; SSH keys not added to the agent; organization SSO tokens that expired; CI jobs missing the GITHUB_TOKEN/GH_TOKEN secret.

Related errors


AI-assisted analysis of vercel-labs/skills@435076e789 (2026-08-28). Data as JSON: /api/errors/c268e7df500cf67d. Report an issue: GitHub.