siyuan-note/siyuan · warning
attribute view order changed; retry the drag
Error message
attribute view order changed; retry the drag
What it means
applyAttributeViewRowOrder is an optimistic-concurrency check: the client submits the row order it previewed plus the expected order it based the drag on. Before applying, the kernel re-serializes the current order (getAttributeViewRowOrder) and compares it with `change.Expected` using reflect.DeepEqual. Any difference — or a missing payload — rejects the drag so the client can retry against fresh data.
Source
Thrown at kernel/model/attribute_view_row_sort.go:232
ret = append(ret, id)
seen[id] = true
}
}
return ret
}
func applyAttributeViewRowOrder(attrView *av.AttributeView, view *av.View, data any) error {
encoded, err := gulu.JSON.MarshalJSON(data)
if nil != err {
return err
}
var change attributeViewRowOrderChange
if err = gulu.JSON.UnmarshalJSON(encoded, &change); nil != err {
return err
}
if nil == change.RowOrder || nil == change.Expected ||
!reflect.DeepEqual(getAttributeViewRowOrder(view), change.Expected) {
return errors.New("attribute view order changed; retry the drag")
}
if len(change.RowOrder.Groups) != len(view.Groups) {
return errors.New("attribute view groups changed; retry the drag")
}
for _, group := range view.Groups {
if _, ok := change.RowOrder.Groups[group.ID]; !ok {
return errors.New("attribute view group not found")
}
}
if nil != change.ValidateGroup && len(change.RowOrder.Sorts) > 0 {
// 预览之后字段值可能变化,提交时再次校验,不能悄悄接受冲突的落点。
copyView, copyErr := cloneAttributeViewRowSort(attrView)
if nil != copyErr {
return copyErr
}
candidate := copyView.GetView(view.ID)
setAttributeViewRowOrder(candidate, change.RowOrder)
collections, renderErr := renderAttributeViewRowSortCollections(copyView, candidate, false)View on GitHub (pinned to 8641553a1f)
Solutions
- Re-open the attribute view, rebuild the drag payload from the current row order, and retry
- Compare the submitted Expected order with the live order to identify what changed, and resolve the concurrent edit first
- Avoid long delays between drag preview and commit; apply the order promptly after preview
Example fix
// before err = applyAttributeViewRowOrder(tx, avID, viewID, staleEncodedChange) // after change := buildRowOrderChange(view) // snapshot from the freshly loaded view err = applyAttributeViewRowOrder(tx, avID, viewID, encode(change))
Defensive patterns
Strategy: retry
Validate before calling
const expected = getCurrentRowOrder(avID, viewID);
if (!deepEqual(expected, payload.Expected)) {
payload = rebuildRowOrderChange(avID, viewID); // refresh before commit
} Try / catch
try {
await sortAttributeViewRow(avID, viewID, encodedChange);
} catch (e) {
if (String(e.msg).includes("order changed")) {
await reloadAttributeView(avID);
await retryDragCommit(); // rebuild payload from fresh state
}
} Prevention
- Minimize the delay between drag preview and commit
- Rebuild the Expected snapshot from the live view at commit time
- Listen for data-change push events and cancel stale pending drags
When it happens
Trigger: Calling sortAttributeViewRow with an encoded order change whose `Expected` snapshot no longer matches the live view — rows added/removed/reordered by another client, a sync write, a sort recomputation, or the client sending a payload computed from an outdated view.
Common situations: Multi-window editing of the same database; background sync updating rows between drag preview and commit; filter/sort recalculations that change effective order; replayed stale drag requests.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- attribute view sort values changed; retry the drag
- attribute view rows changed; retry the drag
- attribute view drop target changed; retry the drag
- attribute view groups changed; retry the drag
- no attribute view rows selected
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/8b80dd7f1c095a23.
Report an issue: GitHub.