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

  1. Empty the directory first or use a recursive-removal API path instead of Box.Remove for folders
  2. Treat 'not exist' as success when you need idempotent deletion (check the wrapped errno)
  3. 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

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


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)