siyuan-note/siyuan · error

download failed (tried main and master): %v

Error message

download failed (tried main and master): %v

What it means

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.

Source

Thrown at kernel/util/skill.go:392

		return nil, "", fmt.Errorf("invalid download URL: %s", src.downloadURL)
	}
	if cerr := CheckHostSSRF(u.Hostname()); cerr != nil {
		return nil, "", cerr
	}

	data, contentType, err = fetchBytes(src.downloadURL)
	if err == nil {
		return data, contentType, nil
	}

	// codeload main 分支 404 时回退 master
	if src.isZip && src.branch == "main" {
		ownerRepo := strings.TrimPrefix(strings.TrimPrefix(src.downloadURL, "https://codeload.github.com/"), "http://codeload.github.com/")
		ownerRepo = strings.TrimSuffix(ownerRepo, "/zip/refs/heads/main")
		fallback := codeloadSource(ownerRepo, "master")
		data, contentType, ferr := fetchBytes(fallback.downloadURL)
		if ferr != nil {
			return nil, "", fmt.Errorf("download failed (tried main and master): %v", err)
		}
		return data, contentType, nil
	}
	return nil, "", err
}

// fetchBytes 执行带大小限制的 GET
func fetchBytes(rawURL string) (data []byte, contentType string, err error) {
	resp, err := httpclient.NewBrowserRequest().Get(rawURL)
	if err != nil {
		return nil, "", errors.New("download failed: " + err.Error())
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		return nil, "", fmt.Errorf("download failed: HTTP %d", resp.StatusCode)
	}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Provide an explicit branch via the tree/<branch> URL form: https://github.com/owner/repo/tree/develop.
  2. Verify the owner/repo spelling and that the repo is public.
  3. Retry after confirming network access to codeload.github.com.
  4. For private repos, use a release asset or raw URL accessible with the available credentials.

Example fix

// before — default-branch autodetect fails
util.InstallSkill("owner/repo")

// after — pin the actual branch
util.InstallSkill("https://github.com/owner/repo/tree/develop")
Defensive patterns

Strategy: validation

Validate before calling

// prefer an explicit branch to avoid main/master guessing
if isOwnerRepoShorthand(src) {
    // prompt user or default to a known branch via tree/<branch> URL
    src = "https://github.com/" + src + "/tree/main"
}

Try / catch

// retry once, then suggest pinning a branch
res, err := util.InstallSkill(src)
if err != nil && strings.Contains(err.Error(), "tried main and master") {
    return fmt.Errorf("could not fetch repo on main or master; specify the branch, e.g. https://github.com/%s/tree/<branch>", src)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/0f64d19e9c9dd11c. Report an issue: GitHub.