larksuite/cli · error

set_recipients requires non-empty addresses

Error message

set_recipients requires non-empty addresses

What it means

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.

Source

Thrown at shortcuts/mail/draft/model.go:277

	return nil
}

func (op PatchOp) Validate() error {
	switch op.Op {
	case "set_subject":
		if strings.TrimSpace(op.Value) == "" {
			return fmt.Errorf("set_subject requires value")
		}
		if strings.ContainsAny(op.Value, "\r\n") {
			return fmt.Errorf("set_subject: value must not contain CR or LF")
		}
	case "set_recipients":
		if !isRecipientField(op.Field) {
			return fmt.Errorf("recipient field must be one of to/cc/bcc")
		}
		for _, addr := range op.Addresses {
			if strings.TrimSpace(addr.Address) == "" {
				return fmt.Errorf("set_recipients requires non-empty addresses")
			}
		}
	case "add_recipient", "remove_recipient":
		if !isRecipientField(op.Field) {
			return fmt.Errorf("recipient field must be one of to/cc/bcc")
		}
		if strings.TrimSpace(op.Address) == "" {
			return fmt.Errorf("%s requires address", op.Op)
		}
	case "set_reply_to":
		if len(op.Addresses) == 0 {
			return fmt.Errorf("set_reply_to requires addresses")
		}
	case "clear_reply_to":
	case "set_body", "set_reply_body":
	case "replace_body", "append_body":
		if !isBodyKind(op.BodyKind) {
			return fmt.Errorf("body_kind must be text/plain or text/html")

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. 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.
  2. Filter out empty/whitespace entries before constructing the op: build the list with a guard like if strings.TrimSpace(a) != "".
  3. If a recipient is genuinely unknown, drop it from the array rather than sending a blank entry.

Example fix

// before
addresses := strings.Split(recipientList, ",")
// produces an empty entry for "a@x.com,"

// after
var addrs []Address
for _, a := range strings.Split(recipientList, ",") {
    if trimmed := strings.TrimSpace(a); trimmed != "" {
        addrs = append(addrs, Address{Address: trimmed})
    }
}
Defensive patterns

Strategy: validation

Validate before calling

for _, a := range op.Addresses {
    if strings.TrimSpace(a.Address) == "" {
        return fmt.Errorf("empty address in set_recipients")
    }
}

Type guard

func validAddresses(addrs []Address) bool {
    for _, a := range addrs {
        if strings.TrimSpace(a.Address) == "" {
            return false
        }
    }
    return true
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/9f7c6957a655856a. Report an issue: GitHub.