siyuan-note/siyuan · error

resolve asset [%s] failed: %w

Error message

resolve asset [%s] failed: %w

What it means

Thrown by ResolveDataAssetPath (kernel/model/assets.go:967) when filepath.EvalSymlinks fails on the specific asset file's absolute path. Unlike the assets-root errors, this is about the individual file: it fails when the file does not exist, is a broken symlink, or is inaccessible due to permissions.

Source

Thrown at kernel/model/assets.go:967

	resolvedRoot, evalErr := filepath.EvalSymlinks(assetRoot)
	if evalErr != nil {
		err = fmt.Errorf("resolve assets directory [%s] failed: %w", assetRoot, evalErr)
		return
	}
	if assetDirIndex > 0 {
		notebookRoot := filepath.Join(util.DataDir, parts[0])
		resolvedDataDir, dataEvalErr := filepath.EvalSymlinks(util.DataDir)
		resolvedNotebookRoot, notebookEvalErr := filepath.EvalSymlinks(notebookRoot)
		if dataEvalErr != nil || notebookEvalErr != nil ||
			!gulu.File.IsSubPath(resolvedDataDir, resolvedNotebookRoot) ||
			!gulu.File.IsSubPath(resolvedNotebookRoot, resolvedRoot) {
			err = fmt.Errorf("notebook asset path resolves outside notebook directory: %s", assetPath)
			return
		}
	}
	resolvedPath, evalErr := filepath.EvalSymlinks(absPath)
	if evalErr != nil {
		err = fmt.Errorf("resolve asset [%s] failed: %w", absPath, evalErr)
		return
	}
	if !gulu.File.IsSubPath(resolvedRoot, resolvedPath) {
		err = fmt.Errorf("asset path resolves outside assets directory: %s", assetPath)
		return
	}

	relativePath = filepath.ToSlash(dataRelativePath)
	return
}

// ResolveUnusedDataAssetPath 解析 data 相对资源路径,并确认目标当前未被引用。
func ResolveUnusedDataAssetPath(assetPath string) (relativePath, absPath string, err error) {
	relativePath, absPath, err = ResolveDataAssetPath(assetPath)
	if err != nil {
		return
	}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Verify the file at the printed absPath exists: `ls -la <absPath>`.
  2. If deleted, either restore from backup/history or remove the dangling reference from the document.
  3. If it is a broken symlink, recreate the target or remove the link.
  4. Fix read/traverse permissions on the file and its parent directories for the kernel process user.
Defensive patterns

Strategy: validation

Validate before calling

// Verify the asset file exists and is resolvable before calling the resolver, to give a clearer error.
abs := filepath.Join(util.DataDir, filepath.FromSlash(p))
if _, err := filepath.EvalSymlinks(abs); err != nil {
    return fmt.Errorf("asset file missing or inaccessible: %w", err)
}

Try / catch

_, absPath, err := model.ResolveDataAssetPath(p)
if err != nil {
    if strings.Contains(err.Error(), "resolve asset [") {
        // file-level resolution failure (deleted/dangling link/permissions); guide user to restore or remove reference
    }
    return err
}

Prevention

When it happens

Trigger: Calling ResolveDataAssetPath for an asset that was deleted between the time the document referenced it and the time of resolution; resolving a path whose final component is a dangling symlink; resolving a file inside a directory the process cannot read/traverse.

Common situations: Stale references in a document after the user deleted the asset from disk; assets removed by an external sync/cleanup tool; a race where the file is being moved; permission mismatch after a user account change.

Related errors


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