siyuan-note/siyuan · error

: selected Vault path is sensitive (wrapped: Obsidian Vault…

Error message

%w: selected Vault path is sensitive (wrapped: Obsidian Vault path is unsafe)

What it means

validateObsidianVaultRoot wraps errObsidianVaultUnsafePath with 'selected Vault path is sensitive' when util.IsSensitivePath(abs) matches — the chosen path is a system-critical location SiYuan refuses to touch (e.g. root, /etc, /usr, Windows system dirs). This protects users from importing from or writing near OS infrastructure.

Solutions

  1. Choose the actual Obsidian vault folder (one containing a .obsidian directory), not a drive/system root
  2. Fix the code or config that resolves to the sensitive path (log the abs path to inspect it)
  3. Move the vault to a normal user directory such as Documents and select that

Example fix

// before
analyzeVault({ localPath: '/' }); // sensitive
// after
analyzeVault({ localPath: '/home/user/Documents/MyVault' });
Defensive patterns

Strategy: validation

Validate before calling

const real = await fs.promises.realpath(vaultPath);
if (isSensitiveSystemPath(real)) throw new Error('Choose the vault folder, not a system directory');
if (!fs.existsSync(path.join(real, '.obsidian'))) warn('Folder does not look like an Obsidian vault');

Try / catch

try { await analyzeVault(opts); } catch (e) { if (isVaultUnsafe(e) && /sensitive/.test(String(e))) showFolderPickerAgain(); else throw e; }

Prevention

When it happens

Trigger: Calling the analyze/import API with localPath pointing at a sensitive system directory such as '/', '/etc', 'C:\Windows', or the user's home root, depending on IsSensitivePath rules.

Common situations: Misconfigured automation defaulting to '/'; user mistakenly picking a drive root in the folder dialog; a bug in path resolution that collapses the path to a system root.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/import_obsidian.go:577

	if strings.TrimSpace(localPath) == "" {
		return "", fmt.Errorf("%w: path is empty", errObsidianVaultUnreadable)
	}
	abs, err := filepath.Abs(filepath.Clean(localPath))
	if err != nil {
		return "", fmt.Errorf("%w: normalize Vault path: %v", errObsidianVaultUnreadable, err)
	}
	info, err := os.Lstat(abs)
	if err != nil {
		return "", fmt.Errorf("%w: read Vault root: %v", errObsidianVaultUnreadable, err)
	}
	if !info.IsDir() {
		return "", errObsidianVaultNotDirectory
	}
	if info.Mode()&os.ModeSymlink != 0 || isObsidianResolvedLink(abs) {
		return "", fmt.Errorf("%w: Vault root is a symbolic link or reparse point", errObsidianVaultUnsafePath)
	}
	if util.IsSensitivePath(abs) {
		return "", fmt.Errorf("%w: selected Vault path is sensitive", errObsidianVaultUnsafePath)
	}
	workspace, _ := filepath.Abs(filepath.Clean(util.WorkspaceDir))
	if sameObsidianPath(abs, workspace) || gulu.File.IsSubPath(workspace, abs) || gulu.File.IsSubPath(abs, workspace) {
		return "", fmt.Errorf("%w: Vault root and SiYuan workspace contain each other", errObsidianVaultUnsafePath)
	}
	configPath := filepath.Join(abs, ".obsidian")
	configInfo, statErr := os.Lstat(configPath)
	if statErr != nil {
		if os.IsNotExist(statErr) {
			return "", errObsidianVaultConfigMissing
		}
		return "", fmt.Errorf("%w: read Vault config directory: %v", errObsidianVaultUnreadable, statErr)
	}
	if !configInfo.IsDir() || configInfo.Mode()&os.ModeSymlink != 0 || isObsidianResolvedLink(configPath) {
		return "", errObsidianVaultConfigMissing
	}
	return abs, nil
}

View on GitHub (pinned to 9f775e8a12)