{"record":{"id":"ea2b27027062b387","repo":"siyuan-note/siyuan","slug":"invalid-card-layout-v","errorCode":null,"errorMessage":"invalid card layout [%v]","messagePattern":"invalid card layout \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/model/attribute_view.go","lineNumber":1734,"sourceCode":"\terr = av.SaveAttributeView(attrView)\n\treturn\n}\n\nfunc (tx *Transaction) doSetAttrViewCardLayout(operation *Operation) (ret *TxErr) {\n\tif err := setAttrViewCardLayout(operation); nil != err {\n\t\treturn &TxErr{code: TxErrHandleAttributeView, id: operation.AvID, msg: err.Error()}\n\t}\n\treturn\n}\n\nfunc setAttrViewCardLayout(operation *Operation) (err error) {\n\tvalue, err := getAttrViewOperationNumber(operation)\n\tif nil != err {\n\t\treturn\n\t}\n\tlayout := av.CardLayout(value)\n\tif value != math.Trunc(value) || !layout.IsValid() {\n\t\treturn fmt.Errorf(\"invalid card layout [%v]\", value)\n\t}\n\n\tattrView, err := av.ParseAttributeView(operation.AvID)\n\tif err != nil {\n\t\treturn\n\t}\n\tview, err := getAttrViewOperationView(attrView, operation)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tswitch view.LayoutType {\n\tcase av.LayoutTypeGallery:\n\t\tview.Gallery.CardLayout = layout\n\tcase av.LayoutTypeKanban:\n\t\tview.Kanban.CardLayout = layout\n\tdefault:\n\t\treturn av.ErrWrongLayoutType","sourceCodeStart":1716,"sourceCodeEnd":1752,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/attribute_view.go#L1716-L1752","documentation":"Returned by setAttrViewCardLayout (attribute_view.go:1734), dispatched through the transaction action \"setAttrViewCardLayout\". operation.Data must be a float64 (else error 437), a whole number (value == math.Trunc(value)), and av.CardLayout(value).IsValid() — i.e. within [CardLayoutList=0, CardLayoutCompact=1]. The enum has only two members (list layout, compact layout).","triggerScenarios":"Frontend sends setAttrViewCardLayout with a non-integer (e.g. 0.5) or an integer outside 0–1 (e.g. 2). Only two field-layout modes exist for gallery/kanban cards.","commonSituations":"Plugin sends an arbitrary layout code; future layout added to the enum but the guard not updated (here the guard delegates to CardLayout.IsValid so it stays in sync); corrupted persisted value.","solutions":["Send only 0 (CardLayoutList) or 1 (CardLayoutCompact) as an integer.","Derive the value from the UI toggle rather than computing it.","Re-validate with av.CardLayout(value).IsValid() semantics: the value must equal its truncation and be 0 or 1."],"exampleFix":"// before: arbitrary code\ntransaction({ op: \"setAttrViewCardLayout\", data: layoutCode })\n\n// after: only the two valid modes\nconst layout = compact ? 1 : 0\ntransaction({ op: \"setAttrViewCardLayout\", data: layout })","handlingStrategy":"validation","validationCode":"// Card layout has only two modes: 0 (list) and 1 (compact).\nif (![0,1].includes(data) || !Number.isInteger(data)) {\n  throw new Error('card layout must be 0 or 1')\n}","typeGuard":"function isCardLayoutPreset(v: unknown): v is number {\n  return typeof v === 'number' && Number.isInteger(v) && (v === 0 || v === 1)\n}","tryCatchPattern":null,"preventionTips":["Derive the value from the layout toggle (list vs compact).","Remember only two enum members exist (CardLayoutList, CardLayoutCompact).","Keep the guard in sync via av.CardLayout.IsValid semantics."],"tags":["attribute-view","av","gallery","kanban","card","validation","transaction"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}