siyuan-note/siyuan · warning
only local assets/... images are supported
Error message
only local assets/... images are supported
What it means
Returned by PrepareDocumentImage when AssetPathWithoutQuery(assetPath) does not have the prefix "assets/". Only local in-doc assets are eligible for model image input; remote URLs, absolute filesystem paths, and non-assets paths are rejected up front.
Source
Thrown at kernel/model/assets.go:385
seen := map[string]bool{}
for _, assetPath := range paths {
if !strings.HasPrefix(AssetPathWithoutQuery(assetPath), "assets/") || seen[assetPath] {
continue
}
seen[assetPath] = true
refs = append(refs, ImageArtifactRef{Kind: "image", Path: assetPath, DocumentID: bt.RootID})
}
return DocumentImageList{DocumentID: bt.RootID, Images: refs}, nil
}
// PrepareDocumentImage 校验并读取文档实际引用的本地资源图片,供当前模型直接接收图片输入。
func PrepareDocumentImage(documentID, assetPath string) (PreparedDocumentImage, error) {
assetPath = strings.TrimSpace(assetPath)
if assetPath == "" {
return PreparedDocumentImage{}, errors.New("assetPath is required for analyze")
}
if !strings.HasPrefix(AssetPathWithoutQuery(assetPath), "assets/") {
return PreparedDocumentImage{}, errors.New("only local assets/... images are supported")
}
bt, err := resolveMultimodalDocument(documentID)
if err != nil {
return PreparedDocumentImage{}, err
}
if !documentReferencesImage(bt.RootID, assetPath) {
return PreparedDocumentImage{}, errors.New("assetPath is not an image referenced by the document")
}
data, err := ReadAssetBytesInBox(bt.BoxID, assetPath)
if err != nil {
return PreparedDocumentImage{}, fmt.Errorf("read image failed: %w", err)
}
prepared, err := util.PrepareModelImage(
data, documentImageMaxBytes, documentImageMaxPixels, documentImageMaxEdge,
)
if err != nil {
return PreparedDocumentImage{}, err
}View on GitHub (pinned to 251596fc0d)
Solutions
- Only pass paths in the form "assets/<filename>" (optionally with "?box=<boxID>" for encrypted notebooks).
- For remote images, first download them into the document's assets/ directory via the upload API, then call PrepareDocumentImage.
- Use ListDocumentImages to obtain paths guaranteed to be in the accepted form.
Example fix
// before — caller passes a remote URL prepared, err := model.PrepareDocumentImage(docID, "https://example.com/a.png") // after — caller downloads into assets/ first, then uses the local path prepared, err := model.PrepareDocumentImage(docID, "assets/a-20260101000000.png")
Defensive patterns
Strategy: validation
Validate before calling
clean := model.AssetPathWithoutQuery(strings.TrimSpace(assetPath))
if !strings.HasPrefix(clean, "assets/") {
return fmt.Errorf("asset path must be local assets/... form, got %q", assetPath)
} Prevention
- For remote images, download to the doc's assets/ dir first via the upload API.
- Never pass absolute filesystem paths or URLs to PrepareDocumentImage.
- Reuse paths emitted by ListDocumentImages — they are already in the accepted form.
When it happens
Trigger: Passing a network URL (http/https), an absolute path (/home/x/y.png), a relative path outside assets/ (../foo.png), or a path with a leading slash. The check strips any ?query before testing the prefix, so ?box=... suffixes on encrypted-notebook assets are still allowed — only the prefix is rejected.
Common situations: A user pastes a remote image URL expecting it to be analyzed; a caller passes the full disk path instead of the doc-relative assets/... form; a migrated doc still references an old path scheme.
Related errors
- assetPath is required for analyze
- asset path is required
- invalid rich clipboard asset index [%d]
- assetPath is not an image referenced by the document
- prompt is required for image generation
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/218881f0ff94a794.
Report an issue: GitHub.