siyuan-note/siyuan · warning
239
239
Error message
Related operations are being processed, please try again later
What it means
RemoveBox uses a per-notebook sync.Map (boxLock) via LoadOrStore to serialise destructive operations on the same notebook; if an entry already exists for boxID it returns errors.New(Conf.language(239)) = 'Related operations are being processed, please try again later'. The entry is deleted on return (defer boxLock.Delete), so the lock is held only for the duration of one RemoveBox call.
Source
Thrown at kernel/model/mount.go:191
func collectBoxDeletedAttributeViewBlocks(boxID string) (ret map[string]map[string]struct{}, err error) {
rootIDs := treenode.GetRootBlockIDsByBoxID(boxID)
if 1 > len(rootIDs) {
return map[string]map[string]struct{}{}, nil
}
boundAVIDs, err := sql.QueryBoundBlockAVIDsInBox(nil, rootIDs, boxID)
if nil != err {
return nil, err
}
return groupDeletedAttributeViewBlocks(boundAVIDs), nil
}
func RemoveBox(boxID string) (err error) {
if !ast.IsNodeIDPattern(boxID) {
return errors.New("invalid notebook ID")
}
if _, loaded := boxLock.LoadOrStore(boxID, true); loaded {
err = errors.New(Conf.language(239))
return
}
defer boxLock.Delete(boxID)
if util.IsReservedFilename(boxID) {
return fmt.Errorf("can not remove [%s] caused by it is a reserved file", boxID)
}
FlushTxQueue()
sql.FlushQueue()
// 索引和笔记本目录删除后无法再读取 custom-avs,需提前收集;实际删除成功后再清理绑定行。
deletedAttrViewBlockIDs, err := collectBoxDeletedAttributeViewBlocks(boxID)
if nil != err {
return fmt.Errorf("query database-bound blocks in notebook [%s] failed: %w", boxID, err)
}
isUserGuide := IsUserGuide(boxID)
localPath := filepath.Join(util.DataDir, boxID)
if !filelock.IsExist(localPath) {View on GitHub (pinned to 251596fc0d)
Solutions
- Retry after a short delay (the lock is released when the in-flight RemoveBox returns), or better, deduplicate in the caller.
- Disable the remove affordance in the UI while a request is pending to prevent duplicate submissions.
- For automations, guard with an in-app mutex keyed by boxID so only one removal is issued.
- Treat code 239 as transient: surface 'please try again' rather than a hard failure.
Example fix
// before: concurrent duplicate removal model.RemoveBox(boxID) // goroutine A model.RemoveBox(boxID) // goroutine B -> Language(239) // after: serialise per-boxID in the caller boxMu.Lock(boxID); defer boxMu.Unlock(boxID) model.RemoveBox(boxID)
Defensive patterns
Strategy: retry
Validate before calling
// Deduplicate removal requests per boxID in the caller (in-process mutex).
var removeMu sync.Map
func removeOnce(boxID string) error {
if _, loaded := removeMu.LoadOrStore(boxID, true); loaded {
return errors.New("already in progress")
}
defer removeMu.Delete(boxID)
return model.RemoveBox(boxID)
} Type guard
null
Try / catch
// Treat 239 as transient: back off and retry a few times.
for i := 0; i < 3; i++ {
err := model.RemoveBox(boxID)
if err == nil || !isBusyErr(err) { return err }
time.Sleep(time.Duration(100<<i) * time.Millisecond)
} Prevention
- Disable the remove button while a request is pending.
- Deduplicate duplicate API calls client-side.
- Serialise destructive ops per notebook with a caller-side mutex.
When it happens
Trigger: Two concurrent RemoveBox calls (or another operation that acquires boxLock for the same boxID) overlap: the second sees the stored entry and fails immediately. Because the lock is per-boxID, only same-notebook concurrency is affected; different notebooks proceed in parallel.
Common situations: Double-click on a remove button triggering two API calls; a retry storm from a flaky client; an automation that issues duplicate removal requests; a UI that does not disable the button while a request is in flight.
Related errors
- encrypted notebook is locked, please unlock it first
- invalid notebook ID
- can not remove [%s] caused by it is a reserved file
- notebook [%s] was created but could not be opened: %w
- notebook [%s] is closed; run `notebook open --id %s` first
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/f2f56be850784329.
Report an issue: GitHub.