siyuan-note/siyuan · error

invalid asset type [ ]

Error message

invalid asset type [%s]

What it means

MAsset-typed template values may only contain assets of type AssetTypeFile or AssetTypeImage; any other asset type causes normalizeNewItemTemplateValue to fail with 'invalid asset type [%s]'. The check runs per asset inside the MAsset slice before the pruned list is stored.

Solutions

  1. Set the asset Type to "file" or "image" as appropriate
  2. Remove the offending asset from the MAsset list
  3. Move non-file/image attachments to a supported field type
  4. Validate asset.Type against AssetTypeFile/AssetTypeImage before submitting

Example fix

// before
assets := []*av.ValueAsset{{Type: "attachment", Content: "a.pdf"}}
// after
assets := []*av.ValueAsset{{Type: av.AssetTypeFile, Content: "a.pdf"}}
Defensive patterns

Strategy: validation

Validate before calling

for _, a := range v.MAsset {
    if a.Type != av.AssetTypeFile && a.Type != av.AssetTypeImage {
        return fmt.Errorf("asset type %q not allowed", a.Type)
    }
}

Type guard

func validAssetType(a *av.ValueAsset) bool { return a != nil && (a.Type == av.AssetTypeFile || a.Type == av.AssetTypeImage) }

Prevention

When it happens

Trigger: A value passed to PruneInvalidNewItemTemplateFieldValues / normalizeNewItemTemplateFieldValues whose MAsset slice contains a ValueAsset with Type not equal to file or image (e.g. empty string, or a custom/unknown type).

Common situations: Templates hand-edited to reference attachments whose type constant was misspelled; code from another av module writing asset types not covered by the template normalizer.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at kernel/av/new_item_template.go:406

			return nil, errors.New("URL value is missing")
		}
		value.Text, value.Number, value.Date, value.MSelect, value.Email, value.Phone, value.MAsset, value.Checkbox, value.Relation = nil, nil, nil, nil, nil, nil, nil, nil, nil
	case KeyTypeEmail:
		if nil == value.Email {
			return nil, errors.New("email value is missing")
		}
		value.Text, value.Number, value.Date, value.MSelect, value.URL, value.Phone, value.MAsset, value.Checkbox, value.Relation = nil, nil, nil, nil, nil, nil, nil, nil, nil
	case KeyTypePhone:
		if nil == value.Phone {
			return nil, errors.New("phone value is missing")
		}
		value.Text, value.Number, value.Date, value.MSelect, value.URL, value.Email, value.MAsset, value.Checkbox, value.Relation = nil, nil, nil, nil, nil, nil, nil, nil, nil
	case KeyTypeMAsset:
		var assets []*ValueAsset
		for _, asset := range value.MAsset {
			if nil != asset && "" != strings.TrimSpace(asset.Content) {
				if AssetTypeFile != asset.Type && AssetTypeImage != asset.Type {
					return nil, fmt.Errorf("invalid asset type [%s]", asset.Type)
				}
				assets = append(assets, asset)
			}
		}
		value.MAsset = assets
		value.Text, value.Number, value.Date, value.MSelect, value.URL, value.Email, value.Phone, value.Checkbox, value.Relation = nil, nil, nil, nil, nil, nil, nil, nil, nil
	case KeyTypeCheckbox:
		if nil == value.Checkbox {
			return nil, errors.New("checkbox value is missing")
		}
		value.Text, value.Number, value.Date, value.MSelect, value.URL, value.Email, value.Phone, value.MAsset, value.Relation = nil, nil, nil, nil, nil, nil, nil, nil, nil
	case KeyTypeRelation:
		if nil == value.Relation {
			return nil, errors.New("relation value is missing")
		}
		for _, blockID := range value.Relation.BlockIDs {
			if !ast.IsNodeIDPattern(blockID) {
				return nil, fmt.Errorf("invalid relation block ID [%s]", blockID)

View on GitHub (pinned to 9f775e8a12)