{"record":{"id":"16ea0a24b13ae029","repo":"siyuan-note/siyuan","slug":"the-notebook-already-exists","errorCode":null,"errorMessage":"The notebook already exists","messagePattern":"The notebook already exists","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/history.go","lineNumber":617,"sourceCode":"\nfunc RollbackNotebookHistory(historyPath string) (err error) {\n\thistoryPath, err = validateHistoryPath(historyPath)\n\tif err != nil {\n\t\treturn\n\t}\n\tboxID, err := validateNotebookHistoryPath(historyPath)\n\tif err != nil {\n\t\treturn\n\t}\n\tif _, loaded := boxLock.LoadOrStore(boxID, true); loaded {\n\t\treturn errors.New(Conf.Language(239))\n\t}\n\tdefer boxLock.Delete(boxID)\n\n\tfrom := historyPath\n\tto := filepath.Join(util.DataDir, boxID)\n\tif filelock.IsExist(to) {\n\t\treturn errors.New(Conf.Language(371))\n\t}\n\n\tif err = filelock.CopyNewtimes(from, to); err != nil {\n\t\tlogging.LogErrorf(\"copy file [%s] to [%s] failed: %s\", from, to, err)\n\t\treturn\n\t}\n\n\tIncSync()\n\tReloadFiletree()\n\tutil.PushMsg(Conf.Language(372), 3000)\n\treturn nil\n}\n\nfunc validateNotebookHistoryPath(historyPath string) (boxID string, err error) {\n\trel, err := filepath.Rel(util.HistoryDir, historyPath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"invalid notebook history path [%s]\", historyPath)\n\t}","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/history.go#L599-L635","documentation":"Thrown by RollbackNotebookHistory when filelock.IsExist(to) is true, meaning a notebook directory with the target boxID already exists on disk at filepath.Join(util.DataDir, boxID). Notebook history rollback restores a deleted notebook by copying its history directory back to the data directory. If a notebook with the same ID already exists, the restore would overwrite or conflict with live data. The error message is Conf.Language(371) = \"The notebook already exists\".","triggerScenarios":"Calling POST /api/history/rollbackNotebookHistory to restore a notebook from deletion history, but a notebook with the same ID already exists in the data directory. This happens when the user re-created a notebook with the same ID after deleting the original, or the notebook was not actually deleted (the history is from a different delete event).","commonSituations":"User deleted a notebook, created a new notebook that happened to get the same ID (or manually reused the ID), then tries to restore the old notebook from history; the deletion history is stale because the notebook was restored by another means already; filesystem has residual data from a partially completed previous operation.","solutions":["Delete or rename the existing notebook directory at data/<boxID> before attempting the history rollback restore.","If the existing notebook is the one you want, no rollback is needed — the notebook is already present.","If the existing notebook is a different notebook that collided on ID, rename its directory first, then retry the rollback."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Check if the target notebook directory already exists before rollback\nconst targetPath = `${dataDir}/${boxID}`\nif (await pathExists(targetPath)) {\n  // Notebook already exists — do not rollback, or remove the existing dir first\n  throw new Error('Notebook already exists at target path')\n}\nawait post('/api/history/rollbackNotebookHistory', { historyPath })","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check if a notebook with the target ID already exists before attempting history restore.","If the notebook exists and is different, rename or remove it before rollback.","Avoid re-creating notebooks with IDs of deleted notebooks if you plan to restore from history."],"tags":["history","rollback","notebook","conflict","filesystem"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}