{"record":{"id":"9f7c6957a655856a","repo":"larksuite/cli","slug":"set-recipients-requires-non-empty-addresses","errorCode":null,"errorMessage":"set_recipients requires non-empty addresses","messagePattern":"set_recipients requires non-empty addresses","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/mail/draft/model.go","lineNumber":277,"sourceCode":"\treturn nil\n}\n\nfunc (op PatchOp) Validate() error {\n\tswitch op.Op {\n\tcase \"set_subject\":\n\t\tif strings.TrimSpace(op.Value) == \"\" {\n\t\t\treturn fmt.Errorf(\"set_subject requires value\")\n\t\t}\n\t\tif strings.ContainsAny(op.Value, \"\\r\\n\") {\n\t\t\treturn fmt.Errorf(\"set_subject: value must not contain CR or LF\")\n\t\t}\n\tcase \"set_recipients\":\n\t\tif !isRecipientField(op.Field) {\n\t\t\treturn fmt.Errorf(\"recipient field must be one of to/cc/bcc\")\n\t\t}\n\t\tfor _, addr := range op.Addresses {\n\t\t\tif strings.TrimSpace(addr.Address) == \"\" {\n\t\t\t\treturn fmt.Errorf(\"set_recipients requires non-empty addresses\")\n\t\t\t}\n\t\t}\n\tcase \"add_recipient\", \"remove_recipient\":\n\t\tif !isRecipientField(op.Field) {\n\t\t\treturn fmt.Errorf(\"recipient field must be one of to/cc/bcc\")\n\t\t}\n\t\tif strings.TrimSpace(op.Address) == \"\" {\n\t\t\treturn fmt.Errorf(\"%s requires address\", op.Op)\n\t\t}\n\tcase \"set_reply_to\":\n\t\tif len(op.Addresses) == 0 {\n\t\t\treturn fmt.Errorf(\"set_reply_to requires addresses\")\n\t\t}\n\tcase \"clear_reply_to\":\n\tcase \"set_body\", \"set_reply_body\":\n\tcase \"replace_body\", \"append_body\":\n\t\tif !isBodyKind(op.BodyKind) {\n\t\t\treturn fmt.Errorf(\"body_kind must be text/plain or text/html\")","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/mail/draft/model.go#L259-L295","documentation":"Thrown by PatchOp.Validate() in shortcuts/mail/draft/model.go:277 when a set_recipients patch op passes an Address whose value is empty or whitespace-only. The validator walks every entry in op.Addresses and requires each addr.Address to contain non-blank text. It is a client-side pre-flight check so malformed recipient entries never reach the mail draft API.","triggerScenarios":"A patch op {\"op\":\"set_recipients\",\"field\":\"to\",\"addresses\":[{\"address\":\"a@x.com\"},{\"address\":\"  \"}]} — any single entry in the addresses array with an empty, \"\", or whitespace-only address string triggers it, even if other entries are valid.","commonSituations":"Building the addresses array programmatically from parsed email lists where an empty string slipped through (e.g. a trailing comma in \"a@x.com, b@y.com,\" split on commas); template interpolation that left a placeholder blank; deserializing JSON where an Address object exists but its address key was omitted or null.","solutions":["Find the offending entry in the addresses array (the error is wrapped as invalid patch op #N, so check op N) and set its address to a real value.","Filter out empty/whitespace entries before constructing the op: build the list with a guard like if strings.TrimSpace(a) != \"\".","If a recipient is genuinely unknown, drop it from the array rather than sending a blank entry."],"exampleFix":"// before\naddresses := strings.Split(recipientList, \",\")\n// produces an empty entry for \"a@x.com,\"\n\n// after\nvar addrs []Address\nfor _, a := range strings.Split(recipientList, \",\") {\n    if trimmed := strings.TrimSpace(a); trimmed != \"\" {\n        addrs = append(addrs, Address{Address: trimmed})\n    }\n}","handlingStrategy":"validation","validationCode":"for _, a := range op.Addresses {\n    if strings.TrimSpace(a.Address) == \"\" {\n        return fmt.Errorf(\"empty address in set_recipients\")\n    }\n}","typeGuard":"func validAddresses(addrs []Address) bool {\n    for _, a := range addrs {\n        if strings.TrimSpace(a.Address) == \"\" {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":null,"preventionTips":["Split recipient lists on delimiters and trim + drop empty entries immediately.","Never build Address entries from untrimmed template output.","Call Patch.Validate() locally before submitting the whole patch to catch the op index early."],"tags":["mail","validation","patch-op","recipients"],"backgroundTag":"empty-required-field","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}