paperclipai/paperclip · error · Error

GitHub source must be a GitHub or GitHub Enterprise URL, or

Error message

GitHub source must be a GitHub or GitHub Enterprise URL, or owner/repo[/path] shorthand.

What it means

Thrown by normalizeGithubImportSource when the input is neither GitHub shorthand (owner/repo[/path]) nor a valid https URL with at least two path segments. The function only accepts full https GitHub/GHE URLs or the owner/repo shorthand; anything else (bare hostnames, non-https URLs, file paths) is rejected.

Source

Thrown at cli/src/commands/client/company.ts:904

  return url.toString();
}

export function normalizeGithubImportSource(input: string, refOverride?: string): string {
  const trimmed = input.trim();
  const ref = refOverride?.trim();

  if (isGithubShorthand(trimmed)) {
    const [owner, repo, ...repoPath] = trimmed.split("/").filter(Boolean);
    return buildGithubImportUrl({
      owner: owner!,
      repo: repo!,
      ref: ref || "main",
      path: repoPath.join("/"),
    });
  }

  if (!looksLikeRepoUrl(trimmed)) {
    throw new Error("GitHub source must be a GitHub or GitHub Enterprise URL, or owner/repo[/path] shorthand.");
  }
  if (!ref) {
    return trimmed;
  }

  const url = new URL(trimmed);
  const hostname = url.hostname;
  const parts = url.pathname.split("/").filter(Boolean);
  if (parts.length < 2) {
    throw new Error("Invalid GitHub URL.");
  }

  const owner = parts[0]!;
  const repo = parts[1]!;
  const existingPath = normalizeGithubImportPath(url.searchParams.get("path"));
  const existingCompanyPath = normalizeGithubImportPath(url.searchParams.get("companyPath"));
  if (existingCompanyPath) {
    return buildGithubImportUrl({ hostname, owner, repo, ref, companyPath: existingCompanyPath });

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Use the HTTPS web URL: 'https://github.com/owner/repo' or 'https://github.example.com/owner/repo'.
  2. Use shorthand: 'owner/repo' or 'owner/repo/sub/path'.
  3. For GHE, make sure the scheme is https; if your GHE is http-only, file a feature request — the current guard rejects it.
  4. Avoid the SSH form 'git@host:owner/repo.git'; convert it to https://host/owner/repo first.

Example fix

# before
paperclipai company import --source git@github.com:acme/widget.git
# after
paperclipai company import --source https://github.com/acme/widget
# or shorthand
paperclipai company import --source acme/widget
Defensive patterns

Strategy: validation

Validate before calling

function validateGithubSource(source: string): void {
  const trimmed = source.trim();
  const ok = /^https:\/\//i.test(trimmed) || /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+/.test(trimmed);
  if (!ok) {
    throw new Error("Provide an https GitHub URL or owner/repo shorthand.");
  }
}

Type guard

function isAcceptableGithubSource(input: string): boolean {
  const t = input.trim();
  if (!t) return false;
  if (/^https:\/\//i.test(t)) {
    try {
      const u = new URL(t);
      return u.pathname.split("/").filter(Boolean).length >= 2;
    } catch {
      return false;
    }
  }
  return /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+/.test(t);
}

Prevention

When it happens

Trigger: Passing 'git@github.com:owner/repo.git' (SSH form), 'github.com/owner/repo' (no scheme), 'http://...' (non-https), a local filesystem path, or a one-segment URL like 'https://github.com/owner'. looksLikeRepoUrl returns false for all of these.

Common situations: Copying the SSH clone URL from GitHub's green button instead of the HTTPS web URL. Pasting a bare 'owner/repo' with a trailing slash that breaks segment checks. Using a GHE URL on http instead of https.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/9aeb0d15c392e0d4. Report an issue: GitHub.