siyuan-note/siyuan · error

skill source too large (limit 10MB)

Error message

skill source too large (limit 10MB)

What it means

fetchBytes enforces a 10MB size cap on skill sources by reading at most maxSkillDownloadBytes+1 bytes; if more than maxSkillDownloadBytes bytes arrive, it aborts with 'skill source too large (limit 10MB)'. This protects the workspace from oversized downloads.

Solutions

  1. Point at a smaller source: a subdirectory tree URL containing only the skill instead of the whole repo
  2. Use a direct link to the individual SKILL.md (raw.githubusercontent.com) or a slim release asset
  3. Trim large files from the source repo/release and retry
  4. If the source is legitimately needed in full, the 10MB limit is fixed at maxSkillDownloadBytes in kernel/util/skill.go — self-host a trimmed archive instead

Example fix

// before
InstallSkill("https://github.com/owner/huge-monorepo") // zip > 10MB
// after
InstallSkill("https://github.com/owner/huge-monorepo/tree/main/skills/my-skill")
Defensive patterns

Strategy: validation

Validate before calling

const r = await fetch(downloadUrl, { method: "HEAD" })
const size = Number(r.headers.get("content-length") || 0)
if (size > 10 * 1024 * 1024) throw new Error(`source exceeds 10MB limit (${size} bytes)`)

Try / catch

try {
  await installSkill(src)
} catch (e) {
  if (String(e).includes("skill source too large")) {
    showHint("Use a subdirectory tree URL or a direct SKILL.md link instead of the full repo")
  }
}

Prevention

When it happens

Trigger: Downloading a repo zip (codeload) or direct-link file whose uncompressed-but-transferred body exceeds 10MB — e.g. a large monorepo zip or a release asset over the cap.

Common situations: Installing a skill from a repository that contains large binaries/history artifacts inflating the zip; a release asset (e.g. containing images or datasets) over 10MB; a self-hosted zip that is simply too big.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/4e9b5e1617762bd5. Report an issue: GitHub.

Appendix: source

Thrown at kernel/util/skill.go:719

// 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
	}
	defer os.RemoveAll(tmpRoot)

	zipPath := filepath.Join(tmpRoot, "src.zip")
	if err := os.WriteFile(zipPath, data, 0644); err != nil {
		return nil, err
	}
	unzipDir := filepath.Join(tmpRoot, "unzip")
	if err := os.MkdirAll(unzipDir, 0755); err != nil {

View on GitHub (pinned to 9f775e8a12)