siyuan-note/siyuan · error
failed to make directory
Error message
failed to make directory: %w
What it means
os.MkdirAll failed when siyuan.storage.put tried to create the parent directories of the target file inside the plugin's storage directory (mode 0755). The wrapped OS error (%w) explains the cause — most often a permission problem, an existing non-directory file at a path component, or an invalid/over-long path.
Solutions
- Read the wrapped OS error in the rejection to identify the failing component
- Check that no file exists at any parent segment of the target path; remove or rename it (via siyuan.storage.remove or the filesystem)
- Verify the workspace directory and plugin storage dir are writable by the kernel process
- Shorten the path if it may exceed filesystem name/length limits
Example fix
// before
await siyuan.storage.put("data/config/app.json", s); // "data/config" exists as a FILE
// after
await siyuan.storage.remove("data/config").catch(() => {}); // clear conflicting file
await siyuan.storage.put("data/config/app.json", s); Defensive patterns
Strategy: try-catch
Validate before calling
// ensure no parent segment is used as both file and directory
if (usedAsFile.has(parentDir)) throw new Error(`"${parentDir}" is already a file`); Type guard
null
Try / catch
try { await siyuan.storage.put(path, content); } catch (e) { if (String(e.message).includes("failed to make directory")) console.error("mkdir failed:", e.message); throw e; } Prevention
- Never reuse the same relative path as both a file and a directory prefix
- Keep storage paths short and shallow to dodge length limits
- Confirm the workspace volume is writable and not full before nested writes
- Avoid paths whose parent segments depend on user input that could collide
When it happens
Trigger: A parent path component exists as a regular file (e.g. "data" is a file, so "data/x.json" cannot be created); the storage directory or a parent is read-only on disk; the workspace volume is full or the path exceeds NAME_MAX/MAX_PATH limits.
Common situations: Plugins writing to nested paths like "cache/http/resp.json" where a previous version stored a file at "cache"; running SiYuan from a location without write permissions; sync tools replacing directories with files.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- create AI editor actions directory failed
- create conf dir failed
- create import dir failed:
- create plugin dir [ ] failed
- failed to remove storage path from watcher
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/5045faeefb6849a0.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/plugin/api_storage.go:278
err = fmt.Errorf("panic during siyuan.storage.put: %v", r)
}
p.worker.Run(func(rt *goja.Runtime) (_ any, _ error) {
if lo.IsNil(err) {
if resolveErr := resolve(result); resolveErr != nil {
logging.LogErrorf("[plugin:%s] siyuan.storage.put resolve: %v", p.Name, resolveErr)
}
} else {
if rejectErr := reject(rt.NewGoError(err)); rejectErr != nil {
logging.LogErrorf("[plugin:%s] siyuan.storage.put reject: %v", p.Name, rejectErr)
}
}
return
}, nil)
}()
if mkdirErr := os.MkdirAll(filepath.Dir(abs), 0755); mkdirErr != nil {
err = fmt.Errorf("failed to make directory: %w", mkdirErr)
return
}
if writeErr := filelock.WriteFile(abs, []byte(content)); writeErr != nil {
err = fmt.Errorf("failed to write file: %w", writeErr)
return
}
return
}()
return
}, func(rt *goja.Runtime, result any, err error) {
if !lo.IsNil(err) {
if rejectErr := reject(rt.NewGoError(err)); rejectErr != nil {
logging.LogErrorf("[plugin:%s] siyuan.storage.put reject: %v", p.Name, rejectErr)
}
}
})
if runErr != nil {View on GitHub (pinned to 9f775e8a12)