{"record":{"id":"0f64d19e9c9dd11c","repo":"siyuan-note/siyuan","slug":"download-failed-tried-main-and-master-v","errorCode":null,"errorMessage":"download failed (tried main and master): %v","messagePattern":"download failed \\(tried main and master\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/skill.go","lineNumber":392,"sourceCode":"\t\treturn nil, \"\", fmt.Errorf(\"invalid download URL: %s\", src.downloadURL)\n\t}\n\tif cerr := CheckHostSSRF(u.Hostname()); cerr != nil {\n\t\treturn nil, \"\", cerr\n\t}\n\n\tdata, contentType, err = fetchBytes(src.downloadURL)\n\tif err == nil {\n\t\treturn data, contentType, nil\n\t}\n\n\t// codeload main 分支 404 时回退 master\n\tif src.isZip && src.branch == \"main\" {\n\t\townerRepo := strings.TrimPrefix(strings.TrimPrefix(src.downloadURL, \"https://codeload.github.com/\"), \"http://codeload.github.com/\")\n\t\townerRepo = strings.TrimSuffix(ownerRepo, \"/zip/refs/heads/main\")\n\t\tfallback := codeloadSource(ownerRepo, \"master\")\n\t\tdata, contentType, ferr := fetchBytes(fallback.downloadURL)\n\t\tif ferr != nil {\n\t\t\treturn nil, \"\", fmt.Errorf(\"download failed (tried main and master): %v\", err)\n\t\t}\n\t\treturn data, contentType, nil\n\t}\n\treturn nil, \"\", err\n}\n\n// fetchBytes 执行带大小限制的 GET\nfunc fetchBytes(rawURL string) (data []byte, contentType string, err error) {\n\tresp, err := httpclient.NewBrowserRequest().Get(rawURL)\n\tif err != nil {\n\t\treturn nil, \"\", errors.New(\"download failed: \" + err.Error())\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode >= 400 {\n\t\treturn nil, \"\", fmt.Errorf(\"download failed: HTTP %d\", resp.StatusCode)\n\t}\n","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/util/skill.go#L374-L410","documentation":"Thrown by downloadSkillSource after the codeload zip download fails on the 'main' branch and the automatic fallback to 'master' also fails. The error wraps the original main-branch error. It means the repository could not be fetched as a zip from either default branch name.","triggerScenarios":"Installing owner/repo shorthand or a bare github.com repo whose default branch is neither 'main' nor 'master' (e.g. 'develop', 'trunk'); the repo does not exist; codeload.github.com is unreachable; the repo is private and requires auth.","commonSituations":"Repository uses a non-standard default branch; 404 because owner/repo is wrong; rate-limited or blocked by GitHub; private repo without credentials; transient network outage.","solutions":["Provide an explicit branch via the tree/<branch> URL form: https://github.com/owner/repo/tree/develop.","Verify the owner/repo spelling and that the repo is public.","Retry after confirming network access to codeload.github.com.","For private repos, use a release asset or raw URL accessible with the available credentials."],"exampleFix":"// before — default-branch autodetect fails\nutil.InstallSkill(\"owner/repo\")\n\n// after — pin the actual branch\nutil.InstallSkill(\"https://github.com/owner/repo/tree/develop\")","handlingStrategy":"validation","validationCode":"// prefer an explicit branch to avoid main/master guessing\nif isOwnerRepoShorthand(src) {\n    // prompt user or default to a known branch via tree/<branch> URL\n    src = \"https://github.com/\" + src + \"/tree/main\"\n}","typeGuard":null,"tryCatchPattern":"// retry once, then suggest pinning a branch\nres, err := util.InstallSkill(src)\nif err != nil && strings.Contains(err.Error(), \"tried main and master\") {\n    return fmt.Errorf(\"could not fetch repo on main or master; specify the branch, e.g. https://github.com/%s/tree/<branch>\", src)\n}","preventionTips":["If a repo's default branch is not main/master, install via the tree/<branch> URL form.","Confirm the repository is public before installing.","For private repos, use an accessible release asset or raw URL."],"tags":["skill-management","network","github","download"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}