siyuan-note/siyuan · error
unsupported rich clipboard image extension
Error message
unsupported rich clipboard image extension [%s]
What it means
PrepareRichClipboardAssets only accepts image assets whose file extension (lowercased, taken from the path with any query string stripped via AssetPathWithoutQuery) is in the richClipboardImageExts allowlist; otherwise it returns fmt.Errorf("unsupported rich clipboard image extension [%s]", ext) at kernel/model/clipboard.go:88. This prevents clipboard copy from copying non-image files (the tests explicitly confirm SVG is rejected).
Solutions
- Filter the asset list to allowed image extensions before calling PrepareRichClipboardAssets; drop or separately handle SVGs
- Convert unsupported formats (e.g. SVG) to a supported raster format (PNG) before adding them to the clipboard payload
- Check the richClipboardImageExts allowlist in kernel/model/clipboard.go to know exactly which extensions are accepted
- Strip query strings from asset URLs before extracting the extension (the kernel already does via AssetPathWithoutQuery, but client-side checks should match)
Example fix
// before
assets = append(assets, RichClipboardAsset{Index: i, Path: img.Src}) // may be .svg
// after
ext := strings.ToLower(filepath.Ext(model.AssetPathWithoutQuery(img.Src)))
if _, ok := allowedImageExts[ext]; !ok {
continue // skip or convert unsupported types such as SVG
} Defensive patterns
Strategy: validation
Validate before calling
ext := strings.ToLower(filepath.Ext(model.AssetPathWithoutQuery(p)))
if _, ok := allowedImageExts[ext]; !ok { continue } // skip/convert SVG etc. Prevention
- Filter clipboard candidates to the allowlisted image extensions before calling the kernel
- Convert SVG and other vector formats to PNG before clipboard copy
- Strip query strings before extension checks to mirror kernel behavior
When it happens
Trigger: Calling PrepareRichClipboardAssets with an asset path ending in .svg, .pdf, .webm, or any extension not present in richClipboardImageExts; paths where the query-stripping still leaves an unusual extension (e.g. double extensions like .png.txt).
Common situations: Pasting HTML that references SVG images (common from web page copies); clipboard producers that do not filter to raster image types (png/jpg/jpeg/gif/webp depending on the allowlist); assets with uppercase extensions are fine (lowercased) but genuinely non-image types are not.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- CardDAV: address file extension name is invalid
- Conf.Language(79)
- failed to write file paths to pasteboard
- Field [assets. .box] should be of type [String]
- Field [assets. ] should be of type [Object]
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/daa77e9f28af029e.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/clipboard.go:88
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
}
if ensureErr := ensureReadableAssetLocal(absPath); ensureErr != nil {
return nil, ensureErr
}
destPath, ok := copied[absPath]
if !ok {
group := ExtractBoxIDFromAssetsPath(absPath)
if group == "" {
group = richClipboardGlobalGroup
}
groups[group] = struct{}{}
View on GitHub (pinned to 9f775e8a12)