siyuan-note/siyuan · error

download failed: HTTP %d

Error message

download failed: HTTP %d

What it means

Thrown by fetchBytes when the HTTP response status code is 400 or above. The status number is formatted into the message. It surfaces server-side rejections (not found, forbidden, rate limit, server error) distinctly from transport errors.

Source

Thrown at kernel/util/skill.go:408

		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)
	}

	contentType = resp.Header.Get("Content-Type")
	body, err := io.ReadAll(io.LimitReader(resp.Body, maxSkillDownloadBytes+1))
	if err != nil {
		return nil, "", errors.New("read body failed: " + err.Error())
	}
	if len(body) > maxSkillDownloadBytes {
		return nil, "", errors.New("skill source too large (limit 10MB)")
	}
	return body, contentType, nil
}

// installFromZip 解压 zip 并安装其中的 skill
func installFromZip(data []byte) (*InstallSkillResult, error) {
	tmpRoot := filepath.Join(TempDir, "ai", "skill-install", gulu.Rand.String(7))
	if err := os.MkdirAll(tmpRoot, 0755); err != nil {
		return nil, err

View on GitHub (pinned to 251596fc0d)

Solutions

  1. 404: verify owner/repo, branch name, and file path; prefer the tree/<branch> URL form.
  2. 403: reduce request frequency, wait out the rate-limit window, or authenticate via a token-bearing URL where supported.
  3. 5xx: retry after a short delay; check status.github.com.
  4. For release assets, confirm the exact tag and asset filename from the releases page.
Defensive patterns

Strategy: try-catch

Try / catch

res, err := util.InstallSkill(src)
if err != nil {
    if strings.Contains(err.Error(), "HTTP 404") {
        return errors.New("skill source not found; check the owner/repo, branch, and path")
    }
    if strings.Contains(err.Error(), "HTTP 403") {
        return errors.New("access denied or rate-limited by GitHub; wait and retry, or use an authenticated URL")
    }
    return err
}

Prevention

When it happens

Trigger: 404 for a non-existent repo/file/branch; 403 or 401 for private repos or rate limiting; 5xx for upstream outages; release asset URL returning 404 because the tag/asset name is wrong.

Common situations: Wrong owner/repo or branch (404); GitHub rate limit on unauthenticated codeload (403); private repo (404/401); a release asset renamed or removed; GitHub incident (5xx).

Related errors


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