siyuan-note/siyuan · error
Remove notebook [ ] path [ ] failed
Error message
Remove notebook [%s] path [%s] failed: %s
What it means
Box.Remove deletes a path inside a notebook via filelock.Remove and wraps failure in localized message 7 'Remove notebook [%s] path [%s] failed: %s'. Go's os.Remove only deletes empty directories, so ENOTEMPTY on a folder and ENOENT on an already-gone path are the two most common causes.
Solutions
- Empty the directory first or use a recursive-removal API path instead of Box.Remove for folders
- Treat 'not exist' as success when you need idempotent deletion (check the wrapped errno)
- Verify write permission on the parent directory, which is what governs deletion
Defensive patterns
Strategy: try-catch
Try / catch
try { box.Remove(path) } catch (e) { if (isNotExistErr(e)) { /* already gone: OK for idempotent cleanup */ return nil } if (isDirNotEmptyErr(e)) { return removeRecursivelyFirst(path) } return e } Prevention
- Box.Remove only deletes empty directories — empty folders first or use a recursive path
- Treat ENOENT as success when deletion must be idempotent
When it happens
Trigger: DELETE-style API paths calling Box.Remove on a folder that still contains files, on a path that was already removed, or when permissions deny deletion.
Common situations: Cleanup scripts assuming recursive delete; racing with the kernel's own doc cleanup; retrying after a partially completed removal.
Related errors
- Create notebook [ ] folder [ ] failed
- Move notebook [ ] file [ ] failed
- can not open file, just support open folder only
- can not remove [ ] caused by it is a reserved file
- can not remove [ ] caused by it is not a dir
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/2f3dfb53ad96ecde.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/box.go:488
fromDir := filepath.Join(boxLocalPath, oldDir)
if util.IsEmptyDir(fromDir) {
filelock.Remove(fromDir)
}
}
IncSync()
return nil
}
func (box *Box) Remove(path string) error {
if _, err := box.validateBoxPath(path); err != nil {
return err
}
boxLocalPath := filepath.Join(util.DataDir, box.ID)
filePath := filepath.Join(boxLocalPath, path)
if err := filelock.Remove(filePath); err != nil {
msg := fmt.Sprintf(Conf.Language(7), box.Name, path, err)
logging.LogErrorf("remove [path=%s] in box [%s] failed: %s", path, box.ID, err)
return errors.New(msg)
}
IncSync()
return nil
}
func (box *Box) ListFiles(path string) (ret []*FileInfo) {
// ListFiles 委托给 Ls,后者已有 validateBoxPath
fis, _, err := box.Ls(path)
if err != nil {
return
}
box.listFiles(&fis, &ret)
return
}
func (box *Box) listFiles(files, ret *[]*FileInfo) {
for _, file := range *files {
if file.isdir {View on GitHub (pinned to afa823b6b4)