siyuan-note/siyuan · error

marketplace package contains too many files

Error message

marketplace package contains too many files

What it means

The package archive contains more than maxLocalPackageFileCount (10000) entries. Thrown by extractLocalPackageArchive (kernel/bazaar/local.go:99-100) as a resource/zip-bomb guard before any entry is read. The limit is a hard package constant; it is not configurable per call.

Source

Thrown at kernel/bazaar/local.go:100

	if err != nil || pkg == nil {
		err = errors.New("invalid marketplace package manifest")
		cleanup()
	}
	return
}

func extractLocalPackageArchive(archivePath, destination string) error {
	reader, err := zip.OpenReader(archivePath)
	if err != nil {
		return errors.New("invalid marketplace package archive")
	}
	defer reader.Close()

	if len(reader.File) == 0 {
		return errors.New("marketplace package archive is empty")
	}
	if len(reader.File) > maxLocalPackageFileCount {
		return errors.New("marketplace package contains too many files")
	}

	var declaredTotal uint64
	for _, item := range reader.File {
		if item.UncompressedSize64 > maxLocalPackageFileSize {
			return errors.New("marketplace package contains a file that is too large")
		}
		if ^uint64(0)-declaredTotal < item.UncompressedSize64 {
			return errors.New("marketplace package is too large")
		}
		declaredTotal += item.UncompressedSize64
		if declaredTotal > maxLocalPackageExtractSize {
			return errors.New("marketplace package is too large")
		}
	}

	if err = os.MkdirAll(destination, 0755); err != nil {
		return err

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Exclude node_modules, .git, dist build caches, and other large trees before zipping
  2. Reduce the package to only shipped files (manifest, source/assets, README)
  3. If a legitimate package genuinely needs >10000 files, restructure it (split packages, prune duplicates)

Example fix

# before: zips everything including node_modules
zip -r pkg.zip .

# after: exclude heavy/unneeded trees
zip -r pkg.zip . -x 'node_modules/*' '.git/*' '*/dist/*'
Defensive patterns

Strategy: validation

Validate before calling

func assertFileCount(path string) error {
    r, err := zip.OpenReader(path)
    if err != nil { return err }
    defer r.Close()
    if len(r.File) > 10000 { return fmt.Errorf("archive has %d entries (>10000)", len(r.File)) }
    return nil
}

Try / catch

if _, pkg, src, cleanup, err := bazaar.ExtractLocalPackage(archivePath); err != nil {
    cleanup()
    return err
}

Prevention

When it happens

Trigger: ExtractLocalPackage receives a zip whose len(reader.File) exceeds 10000. Happens when the archive bundles a large dependency tree (e.g. node_modules, vendored libraries, generated assets).

Common situations: A theme/plugin author zipped the whole project including node_modules or .git; a build pipeline included generated file forests; a malicious archive deliberately inflates entry count.

Related errors


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