paperclipai/paperclip · error · Error

Invalid GitHub URL.

Error message

Invalid GitHub URL.

What it means

Thrown by normalizeGithubImportSource after a URL passed looksLikeRepoUrl but its pathname has fewer than two non-empty segments. The function needs at least owner and repo segments; a URL with only a host (or host plus one segment) is considered structurally incomplete even though it parsed.

Source

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

      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 });
  }
  if (existingPath) {
    return buildGithubImportUrl({ hostname, owner, repo, ref, path: existingPath });
  }
  if (parts[2] === "tree") {
    return buildGithubImportUrl({ hostname, owner, repo, ref, path: parts.slice(4).join("/") });
  }
  if (parts[2] === "blob") {
    return buildGithubImportUrl({ hostname, owner, repo, ref, companyPath: parts.slice(4).join("/") });
  }

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Provide a full owner/repo URL: 'https://github.com/acme/widget'.
  2. Verify the URL opens a repository in a browser before pasting it.
  3. If using shorthand, ensure both owner and repo are present ('acme/widget', not 'acme').
  4. Re-copy the URL from the GitHub repository page address bar.

Example fix

# before
paperclipai company import --source https://github.com/acme --ref v1
# after
paperclipai company import --source https://github.com/acme/widget --ref v1
Defensive patterns

Strategy: validation

Validate before calling

function ensureGithubUrlHasOwnerRepo(source: string): void {
  const u = new URL(source.trim());
  const segments = u.pathname.split("/").filter(Boolean);
  if (segments.length < 2) {
    throw new Error(`URL needs owner/repo segments: ${source}`);
  }
}

Type guard

function githubUrlHasOwnerRepo(input: string): boolean {
  try {
    const u = new URL(input.trim());
    return u.pathname.split("/").filter(Boolean).length >= 2;
  } catch {
    return false;
  }
}

Prevention

When it happens

Trigger: A URL like 'https://github.com/' or 'https://github.com/acme' (only owner, no repo). A URL whose pathname collapses to empty after split/filter. Edge cases where looksLikeRepoUrl's first pass accepted a URL that fails the deeper segment check when a ref override is supplied.

Common situations: Truncated copy-paste of a repo URL. Typing the owner but forgetting the repo. A ref override (--ref) being applied to a malformed URL.

Related errors


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