siyuan-note/siyuan · error

Conf.Language(12)

Error message

Conf.Language(12)

What it means

GetAssetAbsPathInBox fails to resolve an asset file path inside a specific notebook (box). The localized message Conf.Language(12) formats as "Query asset failed [%s]" with the relative asset path. It is thrown when deferred resolution failed and the box is encrypted, so direct filesystem lookup is intentionally skipped because encrypted-notebook assets are isolated and must not leak outside the encryption boundary.

Solutions

  1. Check IsEncryptedBox(boxID) before calling and route through the encrypted-asset read path (e.g. deferredAssetPath / serveEncryptedAsset) instead of direct path resolution
  2. Verify the asset actually exists in the encrypted box's storage; if it was moved or renamed, update the doc's asset links
  3. If the box was encrypted after the asset was added, re-index the notebook so the deferred asset mapping is up to date
  4. Handle the error as 'asset unavailable in encrypted box' and surface a user-facing message rather than retrying the same lookup

Example fix

// before
path, err := model.GetAssetAbsPathInBox(relPath, boxID)
if err != nil { log.Fatal(err) }
// after
if model.IsEncryptedBox(boxID) {
    path, err = model.DeferredAssetPath(relPath, boxID) // encrypted-aware resolution
} else {
    path, err = model.GetAssetAbsPath(relPath)
}
if err != nil { return fmt.Errorf("asset %s unavailable: %w", relPath, err) }
Defensive patterns

Strategy: validation

Validate before calling

if model.IsEncryptedBox(boxID) {
    // use encrypted-aware resolution instead of GetAssetAbsPathInBox
}

Try / catch

path, err := model.GetAssetAbsPathInBox(rel, boxID)
if err != nil {
    return fmt.Errorf("asset %s unavailable in box %s: %w", rel, boxID, err)
}

Prevention

When it happens

Trigger: Calling GetAssetAbsPathInBox(relativePath, boxID) where deferredAssetPath returns nothing (or errors that are treated as not-found) and IsEncryptedBox(boxID) is true, so the function returns fmt.Errorf(Conf.Language(12), relativePath) instead of searching the encrypted box's files directly.

Common situations: Resolving an image or file annotation path for a doc in an encrypted notebook while the asset record still points at the encrypted box; exporters (prepareExportAssets) or size probes (GetAssetImgSizeInBox) hitting encrypted-box assets whose on-disk names differ from the logical asset path.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/3037bb5cc2857080. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/assets.go:1265

			// 验证解析后的路径仍在 <boxID>/assets/ 或全局 data/assets/ 下
			expectedPrefix := filepath.Join(util.DataDir, "assets")
			if boxID != "" {
				expectedPrefix = filepath.Join(util.DataDir, boxID, "assets")
			}
			if !gulu.File.IsSubPath(expectedPrefix, realP) {
				return "", fmt.Errorf("symlink [%s] resolves outside assets directory: [%s]", p, realP)
			}
		}
		return p, nil
	}
	// 非加密 box 的资源可能回退到全局 data/assets(兼容旧笔记本结构)
	if deferredPath, deferredErr := deferredAssetPath(relativePath, boxID, true); deferredErr != nil || deferredPath != "" {
		return deferredPath, deferredErr
	}
	if !IsEncryptedBox(boxID) {
		return GetAssetAbsPathWithOpt(relativePath, false)
	}
	return "", fmt.Errorf(Conf.Language(12), relativePath)
}

// GetAssetAbsPathWithOpt 与 GetAssetAbsPath 一致,但可通过 includeEncrypted 控制是否遍历加密 box。
// serveAssets 传 true(下游 serveEncryptedAsset 会按锁定状态 fail-closed),其他调用方传 false(安全跳过)。
func GetAssetAbsPathWithOpt(relativePath string, includeEncrypted bool) (string, error) {
	relativePath = strings.TrimSpace(relativePath)
	if idx := strings.Index(relativePath, "?"); idx >= 0 {
		relativePath = relativePath[:idx]
	}

	absPath, err := getAssetAbsPath(relativePath, includeEncrypted)
	if err == nil && absPath != "" {
		return absPath, nil
	}

	if err != nil {
		return "", err
	}

View on GitHub (pinned to 9f775e8a12)