{"record":{"id":"3869d38821e82c0e","repo":"siyuan-note/siyuan","slug":"email-value-is-missing","errorCode":null,"errorMessage":"email value is missing","messagePattern":"email value is missing","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/av/new_item_template.go","lineNumber":393,"sourceCode":"\t\tvar selections []*ValueSelect\n\t\tfor _, selection := range value.MSelect {\n\t\t\tif nil != selection && \"\" != strings.TrimSpace(selection.Content) {\n\t\t\t\tselections = append(selections, selection)\n\t\t\t}\n\t\t}\n\t\tif KeyTypeSelect == key.Type && 1 < len(selections) {\n\t\t\tselections = selections[:1]\n\t\t}\n\t\tvalue.MSelect = selections\n\t\tvalue.Text, value.Number, value.Date, value.URL, value.Email, value.Phone, value.MAsset, value.Checkbox, value.Relation = nil, nil, nil, nil, nil, nil, nil, nil, nil\n\tcase KeyTypeURL:\n\t\tif nil == value.URL {\n\t\t\treturn nil, errors.New(\"URL value is missing\")\n\t\t}\n\t\tvalue.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\n\tcase KeyTypeEmail:\n\t\tif nil == value.Email {\n\t\t\treturn nil, errors.New(\"email value is missing\")\n\t\t}\n\t\tvalue.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\n\tcase KeyTypePhone:\n\t\tif nil == value.Phone {\n\t\t\treturn nil, errors.New(\"phone value is missing\")\n\t\t}\n\t\tvalue.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\n\tcase KeyTypeMAsset:\n\t\tvar assets []*ValueAsset\n\t\tfor _, asset := range value.MAsset {\n\t\t\tif nil != asset && \"\" != strings.TrimSpace(asset.Content) {\n\t\t\t\tif AssetTypeFile != asset.Type && AssetTypeImage != asset.Type {\n\t\t\t\t\treturn nil, fmt.Errorf(\"invalid asset type [%s]\", asset.Type)\n\t\t\t\t}\n\t\t\t\tassets = append(assets, asset)\n\t\t\t}\n\t\t}\n\t\tvalue.MAsset = assets","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/av/new_item_template.go#L375-L411","documentation":"Thrown inside normalizeNewItemTemplateValue (kernel/av/new_item_template.go:392-393) when key.Type == KeyTypeEmail but value.Email is nil. The function clones the incoming Value and then strips every non-email sub-field to nil, so it requires a non-nil *ValueEmail payload to proceed. Without it the template field cannot produce a meaningful default. The strict caller at line 332 wraps this as \"new item template field [<keyID>] value is invalid: email value is missing\" and returns it to the API; the prune caller at line 258 silently deletes the field instead.","triggerScenarios":"Saving an Attribute View new-item template (e.g. via the AV set/save API) where a FieldValues entry has Mode = NewItemFieldValueStatic, the key type is \"email\", but the Value JSON omits the \"email\" key or sets it to null.","commonSituations":"Programmatic AV template creation that reuses one generic Value struct across multiple field types; migrating from an AV schema version that predates email fields; frontend sending a partial value object that only populates some sub-fields.","solutions":["Ensure the value JSON includes a non-null email object, e.g. {\"email\": {\"content\": \"user@example.com\"}}","If no default email is desired, omit the field from the template FieldValues map entirely rather than sending a Value with a nil Email","Construct the value programmatically with Value.Email = &ValueEmail{Content: \"...\"} before persisting"],"exampleFix":"// before\nfieldValue.Value = &av.Value{Type: av.KeyTypeEmail}\n// after\nfieldValue.Value = &av.Value{Type: av.KeyTypeEmail, Email: &av.ValueEmail{Content: \"user@example.com\"}}","handlingStrategy":"validation","validationCode":"// Before calling normalizeNewItemTemplateValue or saving a template:\nfunc validateEmailValue(value *av.Value, key *av.Key) error {\n    if key.Type == av.KeyTypeEmail && value.Email == nil {\n        return fmt.Errorf(\"email key requires a non-nil Value.Email\")\n    }\n    return nil\n}","typeGuard":"func hasEmailValue(v *av.Value) bool {\n    return v != nil && v.Email != nil\n}","tryCatchPattern":null,"preventionTips":["Always populate the type-specific sub-field that matches the key type before saving a template value","When building template values programmatically, use a factory function that sets the correct sub-field per key type","Omit fields from FieldValues entirely if no default value is needed, rather than sending nil sub-fields"],"tags":["attribute-view","validation","new-item-template","go"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}