siyuan-note/siyuan · error
asset path is required
Error message
asset path is required
What it means
ResolveDataAssetPath resolves a data-relative asset path to an absolute path, ensuring the target lies inside a valid assets directory (global assets/ or a notebook's assets/). It first rejects an empty input, since there is nothing to resolve. This is a guard against callers passing an unset or blank path variable.
Solutions
- Supply a non-empty data-relative asset path, e.g. "assets/foo-20240101120000.png" or "<notebookID>/assets/img.png"
- Check where the path value originates and fix the upstream code/parameter so the path is populated before the call
- For API callers, include the required path field in the request payload and validate it client-side before sending
Example fix
// before
rel, abs, err := model.ResolveDataAssetPath(assetPath) // assetPath == ""
// after
if assetPath == "" {
return errors.New("caller must supply an asset path")
}
rel, abs, err := model.ResolveDataAssetPath(assetPath) Defensive patterns
Strategy: validation
Validate before calling
if assetPath == "" {
return errors.New("asset path must be provided")
} Type guard
func hasAssetPath(p string) bool { return strings.TrimSpace(p) != "" } Try / catch
rel, abs, err := model.ResolveDataAssetPath(p)
if err != nil {
if err.Error() == "asset path is required" {
return fmt.Errorf("no asset path supplied for %q operation", op)
}
return err
} Prevention
- Validate request parameters at the API boundary before calling asset helpers
- Fail fast where the path is produced (e.g. check the result of the lookup that yields the path)
- Avoid storing asset paths in variables that can be silently zero-valued; initialize with a sentinel and check
When it happens
Trigger: Calling ResolveDataAssetPath("") directly, or via callers such as assetStat, deferredAssetPathFromFiles, PrepareAgentMessageImage, or ResolveUnusedDataAssetPath when the upstream path value was never populated (e.g. an agent message image with no path, or a missing query/form parameter).
Common situations: A plugin or API client omits the path parameter in an asset-related API request; a script variable holding the asset path is empty because an earlier lookup failed silently; agent message preparation receives an image entry without a path.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- asset path does not belong to a notebook
- asset path escapes data directory
- asset path must be a file
- asset path must be under assets
- asset path [ ] is outside assets directory [ ]
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/81eaf1ad0fc8d435.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/assets.go:1025
sort.Slice(ret, func(i, j int) bool {
return ret[i].Updated > ret[j].Updated
})
}
if Conf.Search.Limit <= len(ret) {
ret = ret[:Conf.Search.Limit]
}
return
}
func GetAssetAbsPath(relativePath string) (string, error) {
return GetAssetAbsPathWithOpt(relativePath, false)
}
// ResolveDataAssetPath 解析 data 相对资源路径,并确保目标位于全局或普通笔记本的资源目录中。
func ResolveDataAssetPath(assetPath string) (relativePath, absPath string, err error) {
if assetPath == "" {
err = errors.New("asset path is required")
return
}
nativePath := filepath.FromSlash(assetPath)
if filepath.IsAbs(nativePath) || filepath.VolumeName(nativePath) != "" ||
(len(nativePath) > 0 && os.IsPathSeparator(nativePath[0])) {
err = fmt.Errorf("asset path must be relative to data directory: %s", assetPath)
return
}
nativePath = filepath.Clean(nativePath)
absPath = filepath.Join(util.DataDir, nativePath)
dataRelativePath, relErr := filepath.Rel(util.DataDir, absPath)
if relErr != nil || dataRelativePath == "." || dataRelativePath == ".." ||
strings.HasPrefix(dataRelativePath, ".."+string(filepath.Separator)) {
err = fmt.Errorf("asset path escapes data directory: %s", assetPath)
return
}View on GitHub (pinned to 9f775e8a12)