siyuan-note/siyuan · error

invalid rich clipboard asset index [%d]

Error message

invalid rich clipboard asset index [%d]

What it means

Returned by PrepareRichClipboardAssets when any asset in the input slice has an Index field less than zero. The Index denotes the positional slot of the image in the rich clipboard payload, so a negative value is treated as invalid input. The %d placeholder is filled with asset.Index.

Source

Thrown at kernel/model/clipboard.go:83

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)))
		if _, ok := richClipboardImageExts[ext]; !ok {
			return nil, fmt.Errorf("unsupported rich clipboard image extension [%s]", ext)
		}

		absPath, resolveErr := GetAssetAbsPathInBox(asset.Path, asset.Box)
		if resolveErr != nil {
			return nil, resolveErr
		}

		destPath, ok := copied[absPath]
		if !ok {
			group := ExtractBoxIDFromAssetsPath(absPath)
			if group == "" {
				group = richClipboardGlobalGroup
			}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Ensure every asset.Index is >= 0 before sending; use 0-based indexing without negative sentinels.
  2. Validate the JSON payload with a schema that enforces minimum 0 on the index field.
  3. If a 'no position' meaning is needed, drop the asset from the array rather than using a negative index.

Example fix

// before
assets = append(assets, RichClipboardAsset{Index: -1, Path: p})

// after
assets = append(assets, RichClipboardAsset{Index: pos, Path: p}) // pos is always >= 0
Defensive patterns

Strategy: validation

Validate before calling

// Reject negative indices before sending
for _, a := range assets {
    if a.Index < 0 { /* drop or clamp to 0 */ }
}

Type guard

func hasValidIndices(assets []RichClipboardAsset) bool {
    for _, a := range assets { if a.Index < 0 { return false } }
    return true
}

Try / catch

if err != nil && strings.Contains(err.Error(), "invalid rich clipboard asset index") { sanitizeIndicesAndRetry() }

Prevention

When it happens

Trigger: An asset struct is constructed with an uninitialized (zero is fine) or explicitly negative Index, typically from deserializing malformed JSON or from an off-by-one in frontend index calculation. The check runs inside the per-asset loop, after the count guard.

Common situations: Frontend assigns -1 as a sentinel for 'no index' instead of using 0; JSON parsing defaults; arithmetic bug that subtracts from a zero-based index producing -1.

Related errors


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