{"record":{"id":"2aeb926d410fd754","repo":"siyuan-note/siyuan","slug":"can-not-get-or-create-rollback-box","errorCode":null,"errorMessage":"can not get or create rollback box","messagePattern":"can not get or create rollback box","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/history.go","lineNumber":1448,"sourceCode":"\tif nil == ret {\n\t\tboxName := \"Rollback\"\n\t\tret = GetBoxByName(boxName)\n\t\tif nil == ret {\n\t\t\tvar id string\n\t\t\tid, err = CreateBox(boxName)\n\t\t\tif nil != err {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t_, err = Mount(id)\n\t\t\tif nil != err {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tret = Conf.Box(id)\n\t\t\tcreated = true\n\t\t}\n\t}\n\tif nil == ret {\n\t\terr = errors.New(\"can not get or create rollback box\")\n\t\treturn\n\t}\n\treturn\n}\n","sourceCodeStart":1430,"sourceCodeEnd":1453,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/history.go#L1430-L1453","documentation":"getRollbackBox resolves the notebook to roll back into: it returns Conf.Box(boxID) if mounted, otherwise falls back to a notebook named \"Rollback\" (creating it if needed). If neither the target box nor a Rollback box can be resolved or created, the kernel throws this error to abort the rollback operation instead of writing history data to an undetermined notebook.","triggerScenarios":"Calling RollbackDocHistory or RollbackRepoSnapshotFile when the original notebook is not in the current configuration AND no notebook named \"Rollback\" exists and the implicit fallback creation fails (e.g. invalid/empty box id, workspace configuration not loaded, box creation path rejected).","commonSituations":"Rolling back history after the source notebook was removed from the workspace or the workspace was switched; corrupted conf.json losing the notebook entry; running the API against a different workspace than the one holding the notebook; tests calling the rollback API with a fabricated box id.","solutions":["Mount (or re-open) the original notebook in the current workspace so Conf.Box(id) succeeds before rolling back","Ensure a notebook named \"Rollback\" exists or can be created; if none exists, create an unencrypted notebook named exactly \"Rollback\"","Verify the boxID passed to the rollback API matches an existing notebook ID in conf.json","Check kernel logs for the preceding workspace/configuration errors and restart the kernel so the notebook list is reloaded"],"exampleFix":"// before: rolling back history of an unmounted box\nrollbackDocHistory(\"20240101120000-abcdefg\", \"/history/...\", \"unmounted-box-id\")\n// after: ensure the box is open first (kernel side)\nif nil == Conf.Box(boxID) {\n    OpenBox(boxID) // mount the notebook before invoking rollback\n}\nbox, _, err := getRollbackBox(boxID)","handlingStrategy":"validation","validationCode":"// caller-side check before rollback\nbox := conf.GetBox(boxID)\nif box == nil {\n    box = model.GetBoxByName(\"Rollback\")\n}\nif box == nil {\n    return fmt.Errorf(\"rollback target notebook %q unavailable; mount it or create a \\\"Rollback\\\" notebook\", boxID)\n}","typeGuard":"func rollbackTargetReady(boxID string) bool {\n    return conf.GetBox(boxID) != nil || model.GetBoxByName(\"Rollback\") != nil\n}","tryCatchPattern":null,"preventionTips":["Do not remove notebooks referenced by pending rollback operations","Keep a notebook named \"Rollback\" in workspaces where you use history rollback","Always call rollback APIs with box IDs taken from Conf.Box listing, not from user input","After switching workspaces, re-verify notebook IDs before issuing rollback calls"],"tags":["go","notebook","rollback","history"],"backgroundTag":"entity-not-found","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}