siyuan-note/siyuan · error
invalid github URL: %s
Error message
invalid github URL: %s
What it means
Thrown by normalizeGitHubURL when a github.com URL path has fewer than two segments (i.e. lacks both owner and repo). The installer requires at least /owner/repo to build a codeload download URL; anything shorter is ambiguous.
Source
Thrown at kernel/util/skill.go:333
// codeloadSource 构造 codeload zip 下载源,branch 用于 main→master 回退
func codeloadSource(ownerRepo, branch string) normalizedSkillSource {
return normalizedSkillSource{
downloadURL: "https://codeload.github.com/" + ownerRepo + "/zip/refs/heads/" + branch,
isZip: true,
branch: branch,
}
}
// normalizeGitHubURL 处理 github.com 的各种路径形态
func normalizeGitHubURL(u *url.URL) (normalizedSkillSource, error) {
// /owner/repo/tree/<branch> 或 /owner/repo/tree/<branch>/<path>
// /owner/repo/commit/<sha>
// /owner/repo/releases/download/<tag>/<asset>
// /owner/repo(默认分支)
parts := strings.Split(strings.Trim(u.Path, "/"), "/")
if len(parts) < 2 {
return normalizedSkillSource{}, fmt.Errorf("invalid github URL: %s", u.String())
}
ownerRepo := parts[0] + "/" + parts[1]
// releases/download/<tag>/<asset>
if len(parts) >= 6 && parts[2] == "releases" && parts[3] == "download" {
asset := parts[5]
// 是否 zip 交由 Content-Type 最终判定,这里仅按 asset 后缀预判
return normalizedSkillSource{downloadURL: u.String(), isZip: strings.HasSuffix(asset, ".zip")}, nil
}
// tree/<branch>[/path] 或 blob/<branch>/...
if len(parts) >= 4 && (parts[2] == "tree" || parts[2] == "blob") {
branch := parts[3]
if parts[2] == "blob" {
// blob 指向单个文件,走 raw
rawPath := strings.Join(parts[4:], "/")
return normalizedSkillSource{
downloadURL: "https://raw.githubusercontent.com/" + ownerRepo + "/" + branch + "/" + rawPath,View on GitHub (pinned to 251596fc0d)
Solutions
- Provide a full repository URL such as https://github.com/owner/repo.
- If targeting a subdirectory, use the tree/<branch>/<path> form with at least owner/repo present.
- Validate the path has at least two segments client-side.
Example fix
// before
util.InstallSkill("https://github.com/owner")
// after
util.InstallSkill("https://github.com/owner/repo") Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(src)
if err == nil && u.Host == "github.com" {
segs := strings.Split(strings.Trim(u.Path, "/"), "/")
if len(segs) < 2 || segs[0] == "" || segs[1] == "" {
return errors.New("github URL must include owner and repo")
}
} Prevention
- Always copy the repository URL from the browser address bar to ensure owner/repo are present.
- Validate github.com paths have at least two segments before submission.
- Reject profile-only URLs (https://github.com/<owner>) in the UI.
When it happens
Trigger: Passing 'https://github.com/' or 'https://github.com/owner' (only one path segment); a URL whose path was stripped to empty by trimming.
Common situations: User copied a profile URL instead of a repository URL; trailing slash trimming collapsed the path; the URL is the GitHub root.
Related errors
- skill source is required
- unrecognized skill source: %s
- download failed (tried main and master): %v
- Failed to update agent session permission
- Agent capability name and description are required
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/4b4cbadba6a07e32.
Report an issue: GitHub.