cli/cli · error
invalid repository URL %q: %w
Error message
invalid repository URL %q: %w
What it means
ParseRepoURL delegates parsing to ghrepo.FromFullName, which accepts forms like "OWNER/REPO", "https://github.com/OWNER/REPO", and "OWNER/REPO@ref". When the non-empty input does not match any accepted shape (wrong segment count, bad URL, extra path components), the parse error is wrapped with the offending raw value included for diagnosis.
Source
Thrown at internal/skills/source/source.go:28
)
const SupportedHost = "github.com"
// BuildRepoURL returns the canonical repository URL stored in skill metadata.
func BuildRepoURL(host, owner, repo string) string {
return ghrepo.GenerateRepoURL(ghrepo.NewWithHost(owner, repo, host), "")
}
// ParseRepoURL parses a repository URL stored in skill metadata.
func ParseRepoURL(raw string) (ghrepo.Interface, error) {
raw = strings.TrimSpace(raw)
if raw == "" {
return nil, fmt.Errorf("repository URL is empty")
}
repo, err := ghrepo.FromFullName(raw)
if err != nil {
return nil, fmt.Errorf("invalid repository URL %q: %w", raw, err)
}
return repo, nil
}
// ParseMetadataRepo extracts repository information from skill metadata.
func ParseMetadataRepo(meta map[string]interface{}) (ghrepo.Interface, bool, error) {
if meta == nil {
return nil, false, nil
}
repoValue, _ := meta["github-repo"].(string)
if repoValue == "" {
return nil, false, nil
}
repo, err := ParseRepoURL(repoValue)
if err != nil {View on GitHub (pinned to 0eeec0b92e)
Solutions
- Normalize the value to OWNER/REPO (e.g. strip https://host, /tree/main suffixes) and retry
- If a URL form is used, ensure it is a well-formed https://github.com/OWNER/REPO link
- Print the raw value from the error and fix the producing field (usually github-repo in SKILL.md metadata)
Example fix
# before github-repo: octocat/my-repo/tree/main # invalid repository URL # after github-repo: octocat/my-repo
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check shape: 1 or 2 non-empty segments, optional scheme+host
parts := strings.Split(strings.TrimPrefix(raw, "https://github.com/"), "/")
if len(parts) < 1 || len(parts) > 2 || parts[0] == "" {
return fmt.Errorf("expected OWNER/REPO form, got %q", raw)
} Try / catch
repo, err := source.ParseRepoURL(raw)
if err != nil {
// err already includes the raw value; log it and reject the metadata
return fmt.Errorf("rejecting skill metadata: %w", err)
} Prevention
- Store repos canonically as OWNER/REPO in metadata
- Strip URL decorations (/tree/main, trailing .git, www.) at authoring time
When it happens
Trigger: Passing strings like "owner" (one segment), "a/b/c/d" (too many segments), "https://github.com" (no owner/repo), values with spaces or control characters, or URLs on unexpected hosts with malformed paths.
Common situations: Hand-edited skill metadata with typos; scripts composing repo strings with a missing slash or an appended branch name in the wrong place; copy-paste of browser URLs that include extra path segments like /tree/main.
Related errors
- repository URL is empty
- username cannot be blank
- ErrLocked
- agent tasks are not supported on this host
- task description file cannot be empty
AI-assisted analysis of cli/cli@0eeec0b92e (2026-08-15).
Data as JSON: /api/errors/2b39716c942a4471.
Report an issue: GitHub.