siyuan-note/siyuan · error
%w: path is empty
Error message
%w: path is empty
What it means
validateObsidianVaultRoot rejects an empty/whitespace-only Vault local path by wrapping errObsidianVaultUnreadable with 'path is empty'. The caller must supply a concrete filesystem path to the Obsidian vault directory before analysis can begin.
Source
Thrown at kernel/model/import_obsidian.go:560
}
ret.Analysis.Warnings = append(ret.Analysis.Warnings, asset.Source.RelPath)
continue
}
ret.ImportAssets[key] = asset
ret.Analysis.ImportableAssetCount++
ret.Analysis.ImportableAssetSize += asset.Source.Size
}
ret.Analysis.UnreferencedFileCount = len(ret.ImportAssets) - len(ret.ReferencedAssets)
if ret.Analysis.UnreferencedFileCount < 0 {
ret.Analysis.UnreferencedFileCount = 0
}
progress(100, "Analysis completed")
return ret, nil
}
func validateObsidianVaultRoot(localPath string) (string, error) {
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)
}View on GitHub (pinned to 8641553a1f)
Solutions
- Pass the absolute path of the Obsidian vault directory (the folder containing .obsidian) in the request
- Validate the path is non-empty on the client before invoking the API
- If path comes from settings/env, check the value exists before starting the import
- Re-open the vault picker in the UI and confirm the selection
Example fix
// before
analyzeObsidianVault("") // throws: path is empty
// after
if vaultPath == "" {
return errors.New("vault path is required")
}
analyzeObsidianVault(vaultPath) Defensive patterns
Strategy: validation
Validate before calling
if strings.TrimSpace(vaultPath) == "" {
return errors.New("vault path is required")
} Type guard
null
Try / catch
_, err := AnalyzeObsidianVault(vaultPath)
if err != nil && strings.Contains(err.Error(), "path is empty") {
promptUserToPickVaultFolder()
} Prevention
- Validate the path input client-side before calling the API
- Persist vaultPath settings and check them on startup
- Never pass empty strings from automation; fail fast with a clear message
When it happens
Trigger: Calling the Obsidian analyze/import API with localPath == "" or only whitespace at kernel/model/import_obsidian.go:560 — e.g. the folder-picker returned nothing or a config field was never filled in.
Common situations: Frontend sends an unset path because the user skipped choosing a vault; a saved settings file lost the vaultPath key; automation passed an env variable that is empty.
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
- invalid session id
- data?.msg || data?.message || window.siyuan.languages._kerne
- wrong layout type
- filter nesting depth exceeds the maximum allowed
- Do not include symbols \ / : * ? " ' < > |
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/ddb61d735ffe425b.
Report an issue: GitHub.