{"record":{"id":"1d99ab9375c9d422","repo":"siyuan-note/siyuan","slug":"key-must-be-a-template-field","errorCode":null,"errorMessage":"key must be a template field","messagePattern":"key must be a template field","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view.go","lineNumber":7613,"sourceCode":"\t}\n\n\tregenAttrViewGroups(attrView)\n\terr = av.SaveAttributeView(attrView)\n\treturn\n}\n\n// SetAttributeViewKeyTemplate 设置模板字段公式，复用字段模板保存和分组更新逻辑。\nfunc SetAttributeViewKeyTemplate(avID, keyID, templateContent string) (err error) {\n\tattrView, err := av.ParseAttributeView(avID)\n\tif nil != err {\n\t\treturn err\n\t}\n\tkey, err := attrView.GetKey(keyID)\n\tif nil != err {\n\t\treturn err\n\t}\n\tif av.KeyTypeTemplate != key.Type {\n\t\treturn errors.New(\"key must be a template field\")\n\t}\n\treturn updateAttributeViewColTemplate(&Operation{\n\t\tAvID: avID, ID: keyID, Typ: string(av.KeyTypeTemplate), Data: templateContent,\n\t})\n}\n\nfunc (tx *Transaction) doUpdateAttrViewColNumberFormat(operation *Operation) (ret *TxErr) {\n\terr := updateAttributeViewColNumberFormat(operation)\n\tif err != nil {\n\t\treturn &TxErr{code: TxErrHandleAttributeView, id: operation.AvID, msg: err.Error()}\n\t}\n\treturn\n}\n\nfunc updateAttributeViewColNumberFormat(operation *Operation) (err error) {\n\tattrView, err := av.ParseAttributeView(operation.AvID)\n\tif err != nil {\n\t\treturn","sourceCodeStart":7595,"sourceCodeEnd":7631,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view.go#L7595-L7631","documentation":"The set-attribute-view-template entry point looks up the target key and asserts that its type is exactly av.KeyTypeTemplate before delegating to updateAttributeViewColTemplate. Updating the template of a non-template column is rejected with this fixed message.","triggerScenarios":"Calling the set template API with a keyID that identifies a text/number/select or other non-template field.","commonSituations":"Using a stale field ID after the column type changed or the column was recreated; pointing the update at the wrong attribute view's key ID.","solutions":["Verify key.Type === \"template\" for the keyID before calling","Pass the key ID of the template column you intend to edit","Convert the column to a template type first if template behavior is needed"],"exampleFix":"// before\nsetAttrViewTemplate(avID, textFieldID, \"=NOW()\") // textFieldID is type \"text\"\n// after\nconst key = attrView.keys.find(k => k.type === \"template\");\nsetAttrViewTemplate(avID, key.id, \"=NOW()\")","handlingStrategy":"validation","validationCode":"const key = (await getAttributeView(avID)).keys.find(k => k.id === keyID);\nif (key && key.type !== \"template\") throw new Error(`key ${keyID} is type ${key.type}, not template`);","typeGuard":"const isTemplateKey = (k: {type: string}): k is {type: \"template\"} => k.type === \"template\";","tryCatchPattern":"try { await setAttrViewTemplate(avID, keyID, tpl); } catch (e) { if (String(e).includes(\"key must be a template field\")) { console.warn(\"wrong column type for template update\"); } else throw e; }","preventionTips":["Check key.type before updating templates","Keep field IDs and their types together in one cache","Refresh cached key metadata after column edits"],"tags":["attribute-view","template","type-mismatch"],"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"}