siyuan-note/siyuan · error

Query notebook failed

Error message

Query notebook failed

What it means

During the document-level assets search, getAssetAbsPath calls ListNotebooks(); failure returns the localized 'Query notebook failed' (Conf.Language(0)). The cause is workspace-level I/O or index trouble - the notebook listing under data/ could not be read - not a problem with the specific asset.

Solutions

  1. Verify the kernel process can read <workspace>/data and fix ownership/permissions
  2. Restart the kernel so the notebook list is rebuilt
  3. Move the workspace back to healthy local storage and reopen it
  4. If the volume reports errors, repair it before continuing
Defensive patterns

Strategy: retry

Validate before calling

if f, err := os.Open(util.DataDir); err != nil {
	// data dir unreadable: fix permissions/mount before resolving assets
} else {
	f.Close()
}

Try / catch

On this error, retry the whole resolution once after confirming data/ is readable; persistent failure means an environment problem (disk, mount, permissions), not an asset problem.

Prevention

When it happens

Trigger: The kernel cannot read the data/ directory (permissions or ownership), the notebook index is corrupt, the disk or network share holding the workspace is failing, or the workspace was moved while the kernel was running.

Common situations: Workspace on a NAS/external drive that dropped; permissions changed by security software; workspace copied between machines under different user accounts.

Related errors


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/6ad0e193c39742c6. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/assets.go:1207

			if rootEvalErr != nil {
				return "", fmt.Errorf("resolve assets root [%s] failed: %w", assetsRoot, rootEvalErr)
			}
			if !gulu.File.IsSubPath(realAssetsRoot, realP) {
				return "", fmt.Errorf("symlink [%s] resolves outside data/assets: [%s]", p, realP)
			}
			// 安全校验使用解析后的路径,返回原路径以便下游与 DataDir 保持同一路径形式
			return p, nil
		}
		return p, nil
	}

	// 在文档同级 assets 文件夹下搜索
	if !strings.HasPrefix(relativePath, "assets/") {
		return "", nil
	}
	notebooks, err := ListNotebooks()
	if err != nil {
		return "", errors.New(Conf.Language(0))
	}
	for _, notebook := range notebooks {
		if !includeEncrypted && IsEncryptedBox(notebook.ID) {
			continue // 加密笔记本的资源不参与全局路径解析(孤岛,资源不跨边界)
		}
		notebookAbsPath := filepath.Join(util.DataDir, notebook.ID)
		filelock.Walk(notebookAbsPath, func(path string, d fs.DirEntry, err error) error {
			if isSkipFile(d.Name()) {
				if d.IsDir() {
					return filepath.SkipDir
				}
				return nil
			}
			if p := filepath.ToSlash(path); strings.HasSuffix(p, relativePath) {
				if gulu.File.IsExist(path) {
					absPath = path
					return fs.SkipAll
				}

View on GitHub (pinned to afa823b6b4)