siyuan-note/siyuan · error

can not get or create rollback box

Error message

can not get or create rollback box

What it means

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.

Source

Thrown at kernel/model/history.go:1448

	if nil == ret {
		boxName := "Rollback"
		ret = GetBoxByName(boxName)
		if nil == ret {
			var id string
			id, err = CreateBox(boxName)
			if nil != err {
				return
			}
			_, err = Mount(id)
			if nil != err {
				return
			}
			ret = Conf.Box(id)
			created = true
		}
	}
	if nil == ret {
		err = errors.New("can not get or create rollback box")
		return
	}
	return
}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Mount (or re-open) the original notebook in the current workspace so Conf.Box(id) succeeds before rolling back
  2. Ensure a notebook named "Rollback" exists or can be created; if none exists, create an unencrypted notebook named exactly "Rollback"
  3. Verify the boxID passed to the rollback API matches an existing notebook ID in conf.json
  4. Check kernel logs for the preceding workspace/configuration errors and restart the kernel so the notebook list is reloaded

Example fix

// before: rolling back history of an unmounted box
rollbackDocHistory("20240101120000-abcdefg", "/history/...", "unmounted-box-id")
// after: ensure the box is open first (kernel side)
if nil == Conf.Box(boxID) {
    OpenBox(boxID) // mount the notebook before invoking rollback
}
box, _, err := getRollbackBox(boxID)
Defensive patterns

Strategy: validation

Validate before calling

// caller-side check before rollback
box := conf.GetBox(boxID)
if box == nil {
    box = model.GetBoxByName("Rollback")
}
if box == nil {
    return fmt.Errorf("rollback target notebook %q unavailable; mount it or create a \"Rollback\" notebook", boxID)
}

Type guard

func rollbackTargetReady(boxID string) bool {
    return conf.GetBox(boxID) != nil || model.GetBoxByName("Rollback") != nil
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/2aeb926d410fd754. Report an issue: GitHub.