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

  1. Supply a non-empty data-relative asset path, e.g. "assets/foo-20240101120000.png" or "<notebookID>/assets/img.png"
  2. Check where the path value originates and fix the upstream code/parameter so the path is populated before the call
  3. 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

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


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)