{"record":{"id":"35240382b3663575","repo":"siyuan-note/siyuan","slug":"attribute-view-groups-changed-retry-the-drag","errorCode":null,"errorMessage":"attribute view groups changed; retry the drag","messagePattern":"attribute view groups changed; retry the drag","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/model/attribute_view_row_sort.go","lineNumber":235,"sourceCode":"\t}\n\treturn ret\n}\n\nfunc applyAttributeViewRowOrder(attrView *av.AttributeView, view *av.View, data any) error {\n\tencoded, err := gulu.JSON.MarshalJSON(data)\n\tif nil != err {\n\t\treturn err\n\t}\n\tvar change attributeViewRowOrderChange\n\tif err = gulu.JSON.UnmarshalJSON(encoded, &change); nil != err {\n\t\treturn err\n\t}\n\tif nil == change.RowOrder || nil == change.Expected ||\n\t\t!reflect.DeepEqual(getAttributeViewRowOrder(view), change.Expected) {\n\t\treturn errors.New(\"attribute view order changed; retry the drag\")\n\t}\n\tif len(change.RowOrder.Groups) != len(view.Groups) {\n\t\treturn errors.New(\"attribute view groups changed; retry the drag\")\n\t}\n\tfor _, group := range view.Groups {\n\t\tif _, ok := change.RowOrder.Groups[group.ID]; !ok {\n\t\t\treturn errors.New(\"attribute view group not found\")\n\t\t}\n\t}\n\tif nil != change.ValidateGroup && len(change.RowOrder.Sorts) > 0 {\n\t\t// 预览之后字段值可能变化，提交时再次校验，不能悄悄接受冲突的落点。\n\t\tcopyView, copyErr := cloneAttributeViewRowSort(attrView)\n\t\tif nil != copyErr {\n\t\t\treturn copyErr\n\t\t}\n\t\tcandidate := copyView.GetView(view.ID)\n\t\tsetAttributeViewRowOrder(candidate, change.RowOrder)\n\t\tcollections, renderErr := renderAttributeViewRowSortCollections(copyView, candidate, false)\n\t\tif nil != renderErr {\n\t\t\treturn renderErr\n\t\t}","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/attribute_view_row_sort.go#L217-L253","documentation":"After the row-order check passes, applyAttributeViewRowOrder compares the number of groups in the submitted RowOrder payload with the live view's group count. A mismatch means the grouping changed since the drag was previewed (group field changed, groups added/removed), so the drag is rejected for retry.","triggerScenarios":"Calling sortAttributeViewRow when the view's grouping was modified between drag preview and commit — user changed the group-by field, a tab re-grouped the view, or the payload was built from an outdated grouped view.","commonSituations":"Two windows grouped the same database differently; a plugin changed the group configuration mid-drag; the client replayed an old payload after the view was re-grouped.","solutions":["Reload the view with its current groups, rebuild the drag payload, and retry","Verify the group configuration (group field/settings) is unchanged before committing the drag","If a group change is intended, cancel the pending drag and re-perform it on the new grouping"],"exampleFix":"// before\npayload.RowOrder.Groups = oldGroups\napplyAttributeViewRowOrder(tx, avID, viewID, encode(payload))\n// after\npayload.RowOrder.Groups = currentGroups(view) // rebuilt from the live view\napplyAttributeViewRowOrder(tx, avID, viewID, encode(payload))","handlingStrategy":"validation","validationCode":"if (payload.RowOrder.Groups.length !== getViewGroupCount(avID, viewID)) {\n  payload = rebuildRowOrderChange(avID, viewID);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await sortAttributeViewRow(avID, viewID, encodedChange);\n} catch (e) {\n  if (String(e.msg).includes(\"groups changed\")) {\n    await reloadAttributeView(avID);\n    // cancel or rebuild the drag against the new grouping\n  }\n}","preventionTips":["Re-read group configuration immediately before commit","Cancel in-flight drags when the group-by field changes","Avoid concurrently editing grouping in multiple windows during a drag"],"tags":["attribute-view","row-sort","groups","optimistic-concurrency"],"backgroundTag":"invalid-state-transition","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"}