siyuan-note/siyuan · error

invalid rich clipboard asset count [%d]

Error message

invalid rich clipboard asset count [%d]

What it means

Returned by PrepareRichClipboardAssets when the number of assets supplied in the slice is less than 1 or greater than 1024. The function performs a bounded batch copy of image assets for rich clipboard pasting and rejects empty or oversized batches up front to cap memory and I/O. The %d placeholder is filled with len(assets).

Source

Thrown at kernel/model/clipboard.go:68

	Index int
	Path  string
	Box   string
}

type RichClipboardPreparedAsset struct {
	Index int    `json:"index"`
	Path  string `json:"path"`
}

type RichClipboardPrepared struct {
	Batch  string                       `json:"batch"`
	Groups []string                     `json:"groups"`
	Assets []RichClipboardPreparedAsset `json:"assets"`
}

func PrepareRichClipboardAssets(assets []RichClipboardAsset) (ret *RichClipboardPrepared, err error) {
	if len(assets) < 1 || 1024 < len(assets) {
		return nil, fmt.Errorf("invalid rich clipboard asset count [%d]", len(assets))
	}

	batch := util.RandString(24)
	groups := map[string]struct{}{}
	copied := map[string]string{}
	ret = &RichClipboardPrepared{Batch: batch}
	defer func() {
		if err != nil {
			cleanupRichClipboardGroups(batch, groups)
		}
	}()

	for _, asset := range assets {
		if asset.Index < 0 {
			return nil, fmt.Errorf("invalid rich clipboard asset index [%d]", asset.Index)
		}

		ext := strings.ToLower(filepath.Ext(AssetPathWithoutQuery(asset.Path)))

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Skip the call entirely when the assets slice is empty (guard with len(assets) == 0 before invoking).
  2. If the batch exceeds 1024, chunk the assets into multiple batches of <=1024 and call PrepareRichClipboardAssets per chunk.
  3. Audit the frontend code that builds the assets array to ensure it only includes genuine image references.

Example fix

// before
prepared, err := PrepareRichClipboardAssets(assets)

// after
if len(assets) == 0 {
    return // nothing to do
}
for i := 0; i < len(assets); i += 1024 {
    end := i + 1024
    if end > len(assets) {
        end = len(assets)
    }
    prepared, err := PrepareRichClipboardAssets(assets[i:end])
    // handle prepared, err
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate count before calling PrepareRichClipboardAssets
const maxRichClipboardAssets = 1024
if len(assets) == 0 || len(assets) > maxRichClipboardAssets {
    // chunk or skip
}

Type guard

func isValidRichClipboardCount(n int) bool { return n >= 1 && n <= 1024 }

Try / catch

if err != nil && strings.Contains(err.Error(), "invalid rich clipboard asset count") { /* chunk or abort */ }

Prevention

When it happens

Trigger: Calling PrepareRichClipboardAssets with an empty slice, or with a slice containing more than 1024 image references (e.g. pasting a document that embeds hundreds of inline images). The check is the very first guard in the function, before any disk work.

Common situations: Frontend paste handler sends an empty assets array because the clipboard contained no images; a large page copy triggers hundreds of embedded images exceeding the 1024 cap; a bug in asset collection produces a nil/empty slice.

Related errors


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