{"record":{"id":"2b39716c942a4471","repo":"cli/cli","slug":"invalid-repository-url-q-w","errorCode":null,"errorMessage":"invalid repository URL %q: %w","messagePattern":"invalid repository URL %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/skills/source/source.go","lineNumber":28,"sourceCode":")\n\nconst SupportedHost = \"github.com\"\n\n// BuildRepoURL returns the canonical repository URL stored in skill metadata.\nfunc BuildRepoURL(host, owner, repo string) string {\n\treturn ghrepo.GenerateRepoURL(ghrepo.NewWithHost(owner, repo, host), \"\")\n}\n\n// ParseRepoURL parses a repository URL stored in skill metadata.\nfunc ParseRepoURL(raw string) (ghrepo.Interface, error) {\n\traw = strings.TrimSpace(raw)\n\tif raw == \"\" {\n\t\treturn nil, fmt.Errorf(\"repository URL is empty\")\n\t}\n\n\trepo, err := ghrepo.FromFullName(raw)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid repository URL %q: %w\", raw, err)\n\t}\n\n\treturn repo, nil\n}\n\n// ParseMetadataRepo extracts repository information from skill metadata.\nfunc ParseMetadataRepo(meta map[string]interface{}) (ghrepo.Interface, bool, error) {\n\tif meta == nil {\n\t\treturn nil, false, nil\n\t}\n\n\trepoValue, _ := meta[\"github-repo\"].(string)\n\tif repoValue == \"\" {\n\t\treturn nil, false, nil\n\t}\n\n\trepo, err := ParseRepoURL(repoValue)\n\tif err != nil {","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/cli/cli/blob/0eeec0b92edbe70199f9768522f831d3534f41ad/internal/skills/source/source.go#L10-L46","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"# before\ngithub-repo: octocat/my-repo/tree/main   # invalid repository URL\n\n# after\ngithub-repo: octocat/my-repo","handlingStrategy":"try-catch","validationCode":"// pre-check shape: 1 or 2 non-empty segments, optional scheme+host\nparts := strings.Split(strings.TrimPrefix(raw, \"https://github.com/\"), \"/\")\nif len(parts) < 1 || len(parts) > 2 || parts[0] == \"\" {\n\treturn fmt.Errorf(\"expected OWNER/REPO form, got %q\", raw)\n}","typeGuard":null,"tryCatchPattern":"repo, err := source.ParseRepoURL(raw)\nif err != nil {\n\t// err already includes the raw value; log it and reject the metadata\n\treturn fmt.Errorf(\"rejecting skill metadata: %w\", err)\n}","preventionTips":["Store repos canonically as OWNER/REPO in metadata","Strip URL decorations (/tree/main, trailing .git, www.) at authoring time"],"tags":["skills","metadata","repository","parsing"],"backgroundTag":null,"analyzedSha":"0eeec0b92edbe70199f9768522f831d3534f41ad","analyzedAt":"2026-08-15T12:31:05.478Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}