{"record":{"id":"2f3dfb53ad96ecde","repo":"siyuan-note/siyuan","slug":"remove-notebook-s-path-s-failed-s","errorCode":null,"errorMessage":"Remove notebook [%s] path [%s] failed: %s","messagePattern":"Remove notebook \\[(.+?)\\] path \\[(.+?)\\] failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/box.go","lineNumber":488,"sourceCode":"\t\tfromDir := filepath.Join(boxLocalPath, oldDir)\n\t\tif util.IsEmptyDir(fromDir) {\n\t\t\tfilelock.Remove(fromDir)\n\t\t}\n\t}\n\tIncSync()\n\treturn nil\n}\n\nfunc (box *Box) Remove(path string) error {\n\tif _, err := box.validateBoxPath(path); err != nil {\n\t\treturn err\n\t}\n\tboxLocalPath := filepath.Join(util.DataDir, box.ID)\n\tfilePath := filepath.Join(boxLocalPath, path)\n\tif err := filelock.Remove(filePath); err != nil {\n\t\tmsg := fmt.Sprintf(Conf.Language(7), box.Name, path, err)\n\t\tlogging.LogErrorf(\"remove [path=%s] in box [%s] failed: %s\", path, box.ID, err)\n\t\treturn errors.New(msg)\n\t}\n\tIncSync()\n\treturn nil\n}\n\nfunc (box *Box) ListFiles(path string) (ret []*FileInfo) {\n\t// ListFiles 委托给 Ls，后者已有 validateBoxPath\n\tfis, _, err := box.Ls(path)\n\tif err != nil {\n\t\treturn\n\t}\n\tbox.listFiles(&fis, &ret)\n\treturn\n}\n\nfunc (box *Box) listFiles(files, ret *[]*FileInfo) {\n\tfor _, file := range *files {\n\t\tif file.isdir {","sourceCodeStart":470,"sourceCodeEnd":506,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/box.go#L470-L506","documentation":"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.","triggerScenarios":"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.","commonSituations":"Cleanup scripts assuming recursive delete; racing with the kernel's own doc cleanup; retrying after a partially completed removal.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"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 }","preventionTips":["Box.Remove only deletes empty directories — empty folders first or use a recursive path","Treat ENOENT as success when deletion must be idempotent"],"tags":["filesystem","notebook","delete","api"],"backgroundTag":"file-delete-failed","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}