siyuan-note/siyuan · error

attribute view [ ] is not a table

Error message

attribute view [%s] is not a table

What it means

GetAttributeViewPasteRows resolves the attribute view's current viewable and asserts it is a *av.Table before computing paste rows. If the view's layout is not a table (e.g. kanban or gallery), the assertion fails and this error is returned — paste-row extraction is only implemented for table layouts.

Solutions

  1. Switch the target view's layout to Table before calling GetAttributeViewPasteRows
  2. Pass the viewID of a table view instead of relying on the default/active view
  3. Handle the error in the caller and fall back to a table view or reject the paste operation

Example fix

// before
rows, _, err := model.GetAttributeViewPasteRows(avID, viewID, groupID, startID, count)
// after
if layout := getViewLayout(avID, viewID); layout != av.LayoutTypeTable {
    return fmt.Errorf("paste requires a table view, got %s", layout)
}
rows, _, err := model.GetAttributeViewPasteRows(avID, viewID, groupID, startID, count)
Defensive patterns

Strategy: validation

Validate before calling

const view = await api.getAttributeView(avID, viewID)
if (view.type !== "Table") { throw new Error(`view ${viewID} is not a table`) }

Type guard

function isTableView(v) { return v != null && v.type === "Table" }

Try / catch

rows, _, err := model.GetAttributeViewPasteRows(avID, viewID, groupID, startID, n)
if err != nil && strings.Contains(err.Error(), "is not a table") {
    return ErrPasteRequiresTableView
}

Prevention

When it happens

Trigger: Calling GetAttributeViewPasteRows for an avID whose active view (or the view resolved for the given viewID) has layout type other than table; pasting rows into a non-table database view.

Common situations: Clipboard paste handler invoked while a kanban/gallery view is selected; switching a view's layout to kanban then programmatically requesting paste rows; stale viewID pointing at a non-table view.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/attribute_view_render.go:292

}

func RenderAttributeView(blockID, avID, viewID, query string, page, pageSize int, groupPaging map[string]any, createIfNotExist, ignoreRows bool) (viewable av.Viewable, attrView *av.AttributeView, err error) {
	viewable, attrView, _, err = RenderAttributeViewWithTarget(blockID, avID, viewID, query, page, pageSize, groupPaging, "", createIfNotExist, ignoreRows, "", "")
	return
}

// GetAttributeViewPasteRows 返回当前表格视图中从指定条目开始的连续行和可安全推断类型的空字段,供粘贴扩充行列。
func GetAttributeViewPasteRows(blockID, avID, viewID, groupID, query, startItemID string, count int) (
	table *av.Table, inferableKeyIDs []string, err error,
) {
	viewable, attrView, err := RenderAttributeView(blockID, avID, viewID, query, 1, math.MaxInt, nil, false, false)
	if nil != err {
		return nil, nil, err
	}

	table, ok := viewable.(*av.Table)
	if !ok {
		return nil, nil, fmt.Errorf("attribute view [%s] is not a table", avID)
	}
	if "" != groupID {
		var groupTable *av.Table
		for _, group := range table.Groups {
			if group.GetID() == groupID {
				groupTable, _ = group.(*av.Table)
				break
			}
		}
		if nil == groupTable {
			return nil, nil, fmt.Errorf("attribute view group [%s] not found", groupID)
		}
		table = groupTable
	}

	rows, err := getAttributeViewPasteRowsFromTable(table, startItemID, count)
	if nil != err {
		return nil, nil, err

View on GitHub (pinned to 9f775e8a12)