siyuan-note/siyuan · error

unsupported attribute view row sort operation

Error message

unsupported attribute view row sort operation %s

What it means

avRowSortOperations converts row-sort transactions; every non-nil value must have Action == "sortAttrViewRow" and data of type *model.AttributeViewRowOrderChange. Any other action string or payload type makes it return this error naming the offending action.

Solutions

  1. Send only items whose Action is exactly "sortAttrViewRow" to this endpoint
  2. Split mixed batches: route other actions to their respective endpoints
  3. Check the Data field is *AttributeViewRowOrderChange with RowOrder/Expected populated

Example fix

// before
{action: "sortAttrViewColRow", data: {...}}
// after
{action: "sortAttrViewRow", data: {rowOrder: [...], expected: [...]}}
Defensive patterns

Strategy: type-guard

Validate before calling

if (op.action !== 'sortAttrViewRow') throw new Error('not a row sort op');
if (!op.data || !Array.isArray(op.data.rowOrder)) throw new Error('missing rowOrder');

Type guard

const isRowSort = (op) => op?.action === 'sortAttrViewRow' && op?.data?.rowOrder != null;

Try / catch

try { await avRowSort(ops) } catch (e) { if (/unsupported attribute view row sort/.test(e)) ops = ops.filter(isRowSort); retry(); }

Prevention

When it happens

Trigger: A transaction item in the batch has a different action (e.g. sortAttrColRow, insertAttrViewRow) but was passed to the row-sort mapping endpoint; or Data is not an AttributeViewRowOrderChange.

Common situations: Frontend/plugin mixing multiple transaction action types in one batch call; API version drift where the action string was renamed; plugin sending the wrong Data shape.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/568f6e3fec151319. Report an issue: GitHub.

Appendix: source

Thrown at kernel/api/av_row_sort.go:52

func avRowOrder(value *model.AttributeViewRowOrder) *apicontract.AVRowOrder {
	if value == nil {
		return nil
	}
	return &apicontract.AVRowOrder{ItemIDs: value.ItemIDs, Groups: value.Groups, Sorts: avContractSlice(value.Sorts, toContractAVViewSort)}
}

func avRowSortOperations(values []*model.Operation) ([]*apicontract.AVRowSortOperation, error) {
	if values == nil {
		return nil, nil
	}
	ret := make([]*apicontract.AVRowSortOperation, len(values))
	for i, value := range values {
		if value == nil {
			continue
		}
		data, ok := value.Data.(*model.AttributeViewRowOrderChange)
		if !ok || value.Action != "sortAttrViewRow" {
			return nil, fmt.Errorf("unsupported attribute view row sort operation %s", value.Action)
		}
		var change *apicontract.AVRowOrderChange
		if data != nil {
			change = &apicontract.AVRowOrderChange{RowOrder: avRowOrder(data.RowOrder), Expected: avRowOrder(data.Expected), ValidateGroup: data.ValidateGroup}
		}
		ret[i] = &apicontract.AVRowSortOperation{Action: value.Action, Data: change, ID: value.ID, RootID: value.RootID, ParentID: value.ParentID, PreviousID: value.PreviousID, NextID: value.NextID, BlockIDs: value.BlockIDs, BlockID: value.BlockID, DeckID: value.DeckID, AvID: value.AvID, SrcIDs: value.SrcIDs, IsDetached: value.IsDetached, Name: value.Name, Typ: value.Typ, Format: value.Format, KeyID: value.KeyID, RowID: value.RowID, IsTwoWay: value.IsTwoWay, BackRelationKeyID: value.BackRelationKeyID, RemoveDest: value.RemoveDest, Layout: string(value.Layout), GroupID: value.GroupID, TargetGroupID: value.TargetGroupID, ViewID: value.ViewID, ViewIDs: value.ViewIDs, IgnoreDefaultFill: value.IgnoreDefaultFill}
	}
	return ret, nil
}

View on GitHub (pinned to 9f775e8a12)