siyuan-note/siyuan · warning
assetPath is required for analyze
Error message
assetPath is required for analyze
What it means
Returned by PrepareDocumentImage when assetPath is empty after strings.TrimSpace. It is a pure input-validation guard emitted before any document lookup, file read, or model call. The message text ("for analyze") reflects the AI-vision use case this function was built for.
Source
Thrown at kernel/model/assets.go:382
return DocumentImageList{}, fmt.Errorf("list document images failed: %w", err)
}
refs := make([]ImageArtifactRef, 0, len(paths))
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,
)View on GitHub (pinned to 251596fc0d)
Solutions
- Trim and check assetPath at the call site before invoking PrepareDocumentImage.
- If the path comes from a request payload, return a 400 with a clear field-level message instead of letting it reach the kernel.
- When the caller has no path yet, call ListDocumentImages first and let the user pick a path.
Example fix
// before
prepared, err := model.PrepareDocumentImage(docID, assetPath)
// after
assetPath = strings.TrimSpace(assetPath)
if assetPath == "" {
return fmt.Errorf("assetPath must be provided")
}
prepared, err := model.PrepareDocumentImage(docID, assetPath) Defensive patterns
Strategy: validation
Validate before calling
assetPath = strings.TrimSpace(assetPath)
if assetPath == "" {
// return early, do not call PrepareDocumentImage
return errors.New("assetPath must be provided")
} Prevention
- Trim and check every user/JSON-supplied path field at the request boundary.
- Make assetPath a required field in request DTOs so missing values fail fast in deserialization.
- Use ListDocumentImages to obtain candidate paths so the caller never has an empty value to pass.
When it happens
Trigger: Calling PrepareDocumentImage(documentID, "") or with a whitespace-only assetPath (e.g. " "). Typically a caller that forgot to bind the path argument, passed an empty selection, or forwarded an unvalidated HTTP/JSON payload field.
Common situations: An AI tool or editor callback invokes PrepareDocumentImage with no currently-selected image; a JSON request body with a missing/null assetPath field deserialized to ""; a refactor that dropped the argument.
Related errors
- only local assets/... images are supported
- 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/f570ce0f893b7d4c.
Report an issue: GitHub.