{"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":"error","filePath":"kernel/model/attribute_view.go","lineNumber":1880,"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":1862,"sourceCodeEnd":1898,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view.go#L1862-L1898","documentation":"setAttrViewCardLayout validates that the value is an integer corresponding to a valid av.CardLayout (layout.IsValid()); fractional values or integers that do not map to a defined layout are rejected. Card layout is an enum and must be one of the predefined variants.","triggerScenarios":"Sending a setAttrViewCardLayout operation with a fractional number or an integer that is not a defined av.CardLayout value (e.g. 99, negative).","commonSituations":"Plugin guesses layout indices after the kernel added new layout variants; UI sends a bit-flag combination instead of a single enum; copy-pasted code using another enum's values.","solutions":["Pass only values from the current av.CardLayout enum (verify with layout.IsValid() equivalent client-side).","Math.floor/validate the number is an integer before sending.","Sync plugin constants with the kernel's CardLayout definitions after upgrading."],"exampleFix":"// before\nsetLayout(avID, 0b11); // bit flags not allowed\n// after\nconst layout = CardLayout.List; // a single defined enum value\nif (Number.isInteger(layout)) setLayout(avID, layout);","handlingStrategy":"validation","validationCode":"const n = Number(value);\nif (!Number.isInteger(n) || !CardLayoutValues.includes(n)) throw new RangeError('invalid card layout');","typeGuard":"const isCardLayout = (v: unknown): v is CardLayout => Number.isInteger(v) && CardLayoutValues.includes(v as CardLayout);","tryCatchPattern":"try { await setCardLayout(avID, value); } catch (e) { if (String(e).includes('invalid card layout')) { await setCardLayout(avID, CardLayout.Table); } else throw e; }","preventionTips":["Only use CardLayout enum members from the current kernel version","Do not send bit-flag combinations where a single enum is expected","Re-validate enum constants after upgrades"],"tags":["attribute-view","enum","validation"],"backgroundTag":"invalid-enum-value","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"}