{"record":{"id":"a3355cbccffb64c0","repo":"siyuan-note/siyuan","slug":"invalid-card-configuration-value-v","errorCode":null,"errorMessage":"invalid card configuration value [%v]","messagePattern":"invalid card configuration value \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/model/attribute_view.go","lineNumber":1824,"sourceCode":"\terr = av.SaveAttributeView(attrView)\n\treturn\n}\n\nfunc getAttrViewOperationView(attrView *av.AttributeView, operation *Operation) (ret *av.View, err error) {\n\tif \"\" != operation.ViewID {\n\t\tret = attrView.GetView(operation.ViewID)\n\t\tif nil == ret {\n\t\t\terr = av.ErrViewNotFound\n\t\t}\n\t\treturn\n\t}\n\treturn getAttrViewViewByBlockID(attrView, operation.BlockID)\n}\n\nfunc getAttrViewOperationNumber(operation *Operation) (ret float64, err error) {\n\tvar ok bool\n\tif ret, ok = operation.Data.(float64); !ok {\n\t\terr = fmt.Errorf(\"invalid card configuration value [%v]\", operation.Data)\n\t}\n\treturn\n}\n\nfunc (tx *Transaction) doSetAttrViewCoverFromAssetKeyID(operation *Operation) (ret *TxErr) {\n\terr := setAttrViewCoverFromAssetKeyID(operation)\n\tif err != nil {\n\t\treturn &TxErr{code: TxErrHandleAttributeView, id: operation.AvID, msg: err.Error()}\n\t}\n\treturn\n}\n\nfunc setAttrViewCoverFromAssetKeyID(operation *Operation) (err error) {\n\tattrView, err := av.ParseAttributeView(operation.AvID)\n\tif err != nil {\n\t\treturn\n\t}\n","sourceCodeStart":1806,"sourceCodeEnd":1842,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/attribute_view.go#L1806-L1842","documentation":"Returned by getAttrViewOperationNumber (attribute_view.go:1824), the shared helper used by setAttrViewCardAspectRatio, setAttrViewCardAspectRatioValue, setAttrViewCardSize, setAttrViewCardWidth, and setAttrViewCardLayout. It type-asserts operation.Data to float64; Go's encoding/json decodes JSON numbers into float64, so any non-numeric payload (string, bool, null, array, object) fails the assertion and yields this error before any range check.","triggerScenarios":"Any of the five card-numeric actions receives an operation.data that is not a JSON number — e.g. a string \"2\", a boolean, null, or an object. Because the assertion happens first, you never reach the per-action range/enum guards (errors 426/427/432/433/434) when the type is wrong.","commonSituations":"Frontend serializes the value as a string (e.g. from an input element's value without Number()); plugin sends null as a \"reset\"; a generic operation builder boxes numbers in objects; JSON built manually with a quoted number.","solutions":["Send operation.data as a JSON number for any of the five card-numeric actions.","Coerce with Number() / parseFloat on the client before building the transaction.","If you see this error, switch focus from the value's range to its JSON type — the guard is purely a type assertion."],"exampleFix":"// before: input.value is a string\ntransaction({ op: \"setAttrViewCardWidth\", data: inputEl.value })\n\n// after: coerce to a number\ntransaction({ op: \"setAttrViewCardWidth\", data: Number(inputEl.value) })","handlingStrategy":"type-guard","validationCode":"// Coerce to a JSON number before building any card-numeric operation.\nconst num = Number(value)\nif (!Number.isFinite(num)) throw new Error('card config value must be a finite number')\nop.data = num","typeGuard":"function isCardConfigNumber(v: unknown): v is number {\n  return typeof v === 'number' && Number.isFinite(v)\n}","tryCatchPattern":null,"preventionTips":["Send operation.data as a JSON number for all five card-numeric actions.","Use Number()/parseFloat() on values coming from input elements.","This error is a type assertion failure — fix the JSON type before worrying about range."],"tags":["attribute-view","av","card","validation","type-assertion","transaction","json"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}