{"record":{"id":"3cb5ba47f2572b00","repo":"siyuan-note/siyuan","slug":"invalid-paste-row-count-d","errorCode":null,"errorMessage":"invalid paste row count [%d]","messagePattern":"invalid paste row count \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view_render.go","lineNumber":386,"sourceCode":"\tret = map[string]struct{}{}\n\tfor _, attrView := range attrViews {\n\t\tif nil == attrView {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, keyValues := range attrView.KeyValues {\n\t\t\tif nil == keyValues || nil == keyValues.Key || av.KeyTypeRollup != keyValues.Key.Type ||\n\t\t\t\tnil == keyValues.Key.Rollup || \"\" == keyValues.Key.Rollup.KeyID {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tret[keyValues.Key.Rollup.KeyID] = struct{}{}\n\t\t}\n\t}\n\treturn\n}\n\nfunc getAttributeViewPasteRowsFromTable(table *av.Table, startItemID string, count int) (rows []*av.TableRow, err error) {\n\tif count < 1 {\n\t\treturn nil, fmt.Errorf(\"invalid paste row count [%d]\", count)\n\t}\n\tstart := -1\n\tfor i, row := range table.Rows {\n\t\tif row.ID == startItemID {\n\t\t\tstart = i\n\t\t\tbreak\n\t\t}\n\t}\n\tif 0 > start {\n\t\treturn nil, fmt.Errorf(\"attribute view item [%s] not found\", startItemID)\n\t}\n\tend := start + min(count, len(table.Rows)-start)\n\treturn table.Rows[start:end], nil\n}\n\nfunc RenderAttributeViewWithTarget(blockID, avID, viewID, query string, page, pageSize int, groupPaging map[string]any, initialLayout av.LayoutType, createIfNotExist, ignoreRows bool, targetItemID, targetGroupID string) (viewable av.Viewable, attrView *av.AttributeView, target *AttributeViewRenderTarget, err error) {\n\tif !ast.IsNodeIDPattern(avID) {\n\t\terr = ErrInvalidID","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view_render.go#L368-L404","documentation":"getAttributeViewPasteRowsFromTable validates that the requested paste row count is at least 1 before slicing table rows. A count below 1 cannot produce a meaningful slice, so it returns this error immediately.","triggerScenarios":"Calling GetAttributeViewPasteRows (directly or via TestGetAttributeViewPasteRowsFromTable) with count <= 0 — e.g. clipboard reported zero rows, or an off-by-one in computing rows-to-paste.","commonSituations":"Pasting an empty clipboard selection; frontend computing row count from an empty parsed clipboard table; passing 0 as a default that was never initialized.","solutions":["Ensure count >= 1 before calling; return early on empty clipboard instead of invoking the API","Fix the clipboard row-count computation so empty pastes are short-circuited upstream","Clamp: if parsed rows is empty, skip the paste entirely rather than requesting 0 rows"],"exampleFix":"// before\nrows, err := getAttributeViewPasteRowsFromTable(table, startID, len(parsedRows))\n// after\nif len(parsedRows) == 0 { return nil } // nothing to paste\nrows, err := getAttributeViewPasteRowsFromTable(table, startID, len(parsedRows))","handlingStrategy":"validation","validationCode":"if (!Number.isInteger(count) || count < 1) { throw new Error(`invalid paste row count ${count}`) }","typeGuard":null,"tryCatchPattern":"rows, err := getAttributeViewPasteRowsFromTable(table, startID, count)\nif err != nil && strings.Contains(err.Error(), \"invalid paste row count\") {\n    return ErrNothingToPaste\n}","preventionTips":["Short-circuit empty clipboard parses before calling the API","Assert count >= 1 in paste entry points","Guard against uninitialized count variables defaulting to 0"],"tags":["validation","paste","argument"],"backgroundTag":"value-out-of-range","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"}