{"record":{"id":"a4956a8e1e8cabc5","repo":"siyuan-note/siyuan","slug":"attribute-view-s-is-not-a-table","errorCode":null,"errorMessage":"attribute view [%s] is not a table","messagePattern":"attribute view \\[(.+?)\\] is not a table","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view_render.go","lineNumber":292,"sourceCode":"}\n\nfunc RenderAttributeView(blockID, avID, viewID, query string, page, pageSize int, groupPaging map[string]any, createIfNotExist, ignoreRows bool) (viewable av.Viewable, attrView *av.AttributeView, err error) {\n\tviewable, attrView, _, err = RenderAttributeViewWithTarget(blockID, avID, viewID, query, page, pageSize, groupPaging, \"\", createIfNotExist, ignoreRows, \"\", \"\")\n\treturn\n}\n\n// GetAttributeViewPasteRows 返回当前表格视图中从指定条目开始的连续行和可安全推断类型的空字段，供粘贴扩充行列。\nfunc GetAttributeViewPasteRows(blockID, avID, viewID, groupID, query, startItemID string, count int) (\n\ttable *av.Table, inferableKeyIDs []string, err error,\n) {\n\tviewable, attrView, err := RenderAttributeView(blockID, avID, viewID, query, 1, math.MaxInt, nil, false, false)\n\tif nil != err {\n\t\treturn nil, nil, err\n\t}\n\n\ttable, ok := viewable.(*av.Table)\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"attribute view [%s] is not a table\", avID)\n\t}\n\tif \"\" != groupID {\n\t\tvar groupTable *av.Table\n\t\tfor _, group := range table.Groups {\n\t\t\tif group.GetID() == groupID {\n\t\t\t\tgroupTable, _ = group.(*av.Table)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif nil == groupTable {\n\t\t\treturn nil, nil, fmt.Errorf(\"attribute view group [%s] not found\", groupID)\n\t\t}\n\t\ttable = groupTable\n\t}\n\n\trows, err := getAttributeViewPasteRowsFromTable(table, startItemID, count)\n\tif nil != err {\n\t\treturn nil, nil, err","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view_render.go#L274-L310","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Switch the target view's layout to Table before calling GetAttributeViewPasteRows","Pass the viewID of a table view instead of relying on the default/active view","Handle the error in the caller and fall back to a table view or reject the paste operation"],"exampleFix":"// before\nrows, _, err := model.GetAttributeViewPasteRows(avID, viewID, groupID, startID, count)\n// after\nif layout := getViewLayout(avID, viewID); layout != av.LayoutTypeTable {\n    return fmt.Errorf(\"paste requires a table view, got %s\", layout)\n}\nrows, _, err := model.GetAttributeViewPasteRows(avID, viewID, groupID, startID, count)","handlingStrategy":"validation","validationCode":"const view = await api.getAttributeView(avID, viewID)\nif (view.type !== \"Table\") { throw new Error(`view ${viewID} is not a table`) }","typeGuard":"function isTableView(v) { return v != null && v.type === \"Table\" }","tryCatchPattern":"rows, _, err := model.GetAttributeViewPasteRows(avID, viewID, groupID, startID, n)\nif err != nil && strings.Contains(err.Error(), \"is not a table\") {\n    return ErrPasteRequiresTableView\n}","preventionTips":["Check the view layout before invoking paste-row APIs","After layout changes, refresh cached view metadata","Route paste operations only through table views in UI code"],"tags":["layout","type-assertion","paste"],"backgroundTag":"incompatible-source-type","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}