crewAIInc/crewAI · error · ValueError
Invalid GitHub URL: {repo_url}
Error message
Invalid GitHub URL: {repo_url} What it means
Raised by GithubLoader.load() when the source string does not start with 'https://github.com/'. The loader only supports that exact scheme+host prefix — no http://, no git@ SSH form, no api.github.com, no trailing variations — so any other URL shape is rejected before parsing owner/repo.
Source
Thrown at lib/crewai-tools/src/crewai_tools/rag/loaders/github_loader.py:30
"""Loader for GitHub repository content."""
def load(self, source: SourceContent, **kwargs: Any) -> LoaderResult: # type: ignore[override]
"""Load content from a GitHub repository.
Args:
source: GitHub repository URL
**kwargs: Additional arguments including gh_token and content_types
Returns:
LoaderResult with repository content
"""
metadata = kwargs.get("metadata", {})
gh_token = metadata.get("gh_token")
content_types = metadata.get("content_types", ["code", "repo"])
repo_url = source.source
if not repo_url.startswith("https://github.com/"):
raise ValueError(f"Invalid GitHub URL: {repo_url}")
parts = repo_url.replace("https://github.com/", "").strip("/").split("/")
if len(parts) < 2:
raise ValueError(f"Invalid GitHub repository URL: {repo_url}")
repo_name = f"{parts[0]}/{parts[1]}"
g = Github(gh_token) if gh_token else Github()
try:
repo = g.get_repo(repo_name)
except GithubException as e:
raise ValueError(f"Unable to access repository {repo_name}: {e}") from e
all_content = []
if "repo" in content_types:
all_content.append(f"Repository: {repo.full_name}")View on GitHub (pinned to 754d7323be)
Solutions
- Normalize the URL before loading: prepend https:// if missing, and convert git@github.com:owner/repo.git to https://github.com/owner/repo.
- If the repo is on GitLab/Bitbucket, this loader cannot fetch it — use a different ingestion path (clone locally and use DirectoryLoader).
- Validate user-supplied URLs with a regex/parser before handing them to the loader.
Example fix
# before
result = GithubLoader().load(SourceContent('github.com/crewAIInc/crewAI')) # no scheme
# after
import re
url = 'github.com/crewAIInc/crewAI'
if url.startswith('git@github.com:'):
url = 'https://github.com/' + url.split(':', 1)[1].removesuffix('.git')
elif not url.startswith('https://'):
url = 'https://' + url
result = GithubLoader().load(SourceContent(url)) Defensive patterns
Strategy: validation
Validate before calling
import re\n\ndef normalize_github_url(url: str) -> str:\n url = url.strip().removesuffix('.git')\n if url.startswith('git@github.com:'):\n url = 'https://github.com/' + url.split(':', 1)[1]\n if not url.startswith('https://'):\n url = 'https://' + url\n return url Type guard
GITHUB_REPO_RE = re.compile(r'^https://github\.com/[^/]+/[^/]+/?$')\n\ndef is_github_repo_url(url: str) -> bool:\n return bool(GITHUB_REPO_RE.match(url))
Prevention
- Normalize SSH/scheme-less forms centrally before any loader call.
- Reject non-GitHub forges early with a clear message.
- Store canonical https URLs in config, not git remotes.
When it happens
Trigger: Passing 'github.com/owner/repo' (missing scheme), 'http://github.com/owner/repo', 'git@github.com:owner/repo.git', or an entirely different host like a GitLab or Gitea URL.
Common situations: Copy-pasting repo URLs that browsers display without the scheme; supporting arbitrary forge URLs in user-facing config where users enter GitLab/Bitbucket links; config files storing SSH remotes from git remote -v output.
Related errors
- Invalid GitHub repository URL: {repo_url}
- URL directory loading is not supported. Please provide a loc
- Directory does not exist: {source_ref}
- Path is not a directory: {source_ref}
- No content could be loaded from repository: {repo_url}
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/c3ee51d5c462b5ff.
Report an issue: GitHub.