siyuan-note/siyuan · error

use template for a template field

Error message

use template for a template field

What it means

UpdateAttributeViewKeyConfig routes each one-key config map to a handler based on the setting name. The 'renderTemplate' setting evaluates a template against a row for non-template fields, while 'template' changes the template expression of a template-typed field. When the target field is already of type 'template', 'renderTemplate' is rejected because it is the wrong setter for that field type.

Solutions

  1. Use the 'template' setting instead of 'renderTemplate' for this field: {"template": "<expression>"}.
  2. Check the field's type first (via the attribute view API) and pick 'template' for template fields, 'renderTemplate' for others.
  3. If the field should not be a template field, change its type via the 'type' setting before using renderTemplate.

Example fix

// before
UpdateAttributeViewKeyConfig(avID, keyID, {"renderTemplate": "=this.price*1.1"})
// after
UpdateAttributeViewKeyConfig(avID, keyID, {"template": "=this.price*1.1"})
Defensive patterns

Strategy: validation

Validate before calling

// JS: check field type before choosing the setting
if (key.type === "template") {
  config = { template: expr };
} else {
  config = { renderTemplate: expr };
}

Type guard

function isTemplateField(key) { return key && key.type === "template"; }

Try / catch

try { await updateKeyConfig(avID, keyID, cfg); } catch (e) { if (String(e).includes("use template for a template field")) { await updateKeyConfig(avID, keyID, { template: cfg.renderTemplate }); } else { throw e; } }

Prevention

When it happens

Trigger: Calling UpdateAttributeViewKeyConfig(avID, keyID, {"renderTemplate": "..."}) where key.Type == av.KeyTypeTemplate (the field was created as a template field).

Common situations: A client script or plugin updates field configs generically and applies renderTemplate to every field it touches, including template fields; or the field's type was switched to template earlier and the caller's cached field-type info is stale.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/401b0459676b1e0c. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/attribute_view_key_config.go:80

			case "icon":
				return setAttributeViewColIcon(op)
			case "desc":
				return setAttributeViewColDesc(op)
			case "numberFormat":
				if av.KeyTypeNumber != key.Type || !slices.Contains(AttributeViewKeyNumberFormats, text) {
					return errors.New("numberFormat requires a number field and a supported format")
				}
				return updateAttributeViewColNumberFormat(op)
			case "dateFormat":
				return setAttributeViewColDateFormat(op)
			case "template":
				if av.KeyTypeTemplate != key.Type {
					return errors.New("template requires a template field; use renderTemplate for other fields")
				}
				return updateAttributeViewColTemplate(op)
			case "renderTemplate":
				if av.KeyTypeTemplate == key.Type {
					return errors.New("use template for a template field")
				}
				return updateAttributeViewColTemplate(op)
			}
		case "autoFillNow", "fillSpecificTime", "includeTime":
			flag, ok := value.(bool)
			if !ok {
				return fmt.Errorf("%s must be a boolean", setting)
			}
			op.Data = flag
			if "includeTime" == setting {
				switch key.Type {
				case av.KeyTypeCreated:
					return setAttrViewCreatedIncludeTime(op)
				case av.KeyTypeUpdated:
					return setAttrViewUpdatedIncludeTime(op)
				}
				return errors.New("includeTime requires a created or updated field")
			}

View on GitHub (pinned to 9f775e8a12)