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

  1. Trim and check assetPath at the call site before invoking PrepareDocumentImage.
  2. If the path comes from a request payload, return a 400 with a clear field-level message instead of letting it reach the kernel.
  3. 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

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


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