larksuite/cli · error
recipient field must be one of to/cc/bcc
Error message
recipient field must be one of to/cc/bcc
What it means
setRecipients validates the recipient field name via isRecipientField; only 'to', 'cc', and 'bcc' (case-insensitive) are accepted. Any other field string is rejected, and the same validation is also applied by buildDraftEditPatch.
Source
Thrown at shortcuts/mail/draft/patch.go:160
case "remove_calendar":
return applyCalendarRemove(snapshot)
default:
return fmt.Errorf("unsupported patch op %q", op.Op)
}
return nil
}
func ensureHeaderEditable(name string, options PatchOptions) error {
if protectedHeaders[strings.ToLower(strings.TrimSpace(name))] && !options.AllowProtectedHeaderEdits {
return fmt.Errorf("header %q is protected; rerun with allow_protected_header_edits", name)
}
return nil
}
func setRecipients(snapshot *DraftSnapshot, field string, addrs []Address) error {
field = strings.ToLower(strings.TrimSpace(field))
if !isRecipientField(field) {
return fmt.Errorf("recipient field must be one of to/cc/bcc")
}
normalized := make([]Address, 0, len(addrs))
seen := map[string]bool{}
for _, addr := range addrs {
if strings.TrimSpace(addr.Address) == "" {
return fmt.Errorf("recipient address is empty")
}
key := strings.ToLower(strings.TrimSpace(addr.Address))
if seen[key] {
continue
}
seen[key] = true
normalized = append(normalized, Address{
Name: addr.Name,
Address: strings.TrimSpace(addr.Address),
})
}
_, headerName := recipientField(snapshot, field)View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Use exactly "to", "cc", or "bcc" (case-insensitive; trim whitespace, drop any colon).
- If you need to change From/Reply-To, use the dedicated ops or header machinery instead of set_recipients.
- Normalize the field in your caller: strings.ToLower(strings.TrimSpace(strings.TrimSuffix(field, ":"))).
Example fix
// before
op := PatchOp{Op: "set_recipients", Field: "To:", Addresses: addrs}
// after
op := PatchOp{Op: "set_recipients", Field: "to", Addresses: addrs} Defensive patterns
Strategy: validation
Validate before calling
var recipientFields = map[string]bool{"to": true, "cc": true, "bcc": true}
func isRecipientField(f string) bool {
f = strings.ToLower(strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(f), ":")))
return recipientFields[f]
} Type guard
func normalizeRecipientField(f string) (string, bool) {
f = strings.ToLower(strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(f), ":")))
return f, recipientFields[f]
} Try / catch
if err := Apply(ctx, dctx, ops, opts); err != nil {
if strings.Contains(err.Error(), "one of to/cc/bcc") {
return fmt.Errorf("use bare field name 'to'|'cc'|'bcc': %w", err)
}
return err
} Prevention
- Use constants ("to", "cc", "bcc") instead of user-facing labels.
- Strip colons and whitespace from field values before patching.
- Route From/Reply-To changes to dedicated ops, not set_recipients.
- Add a table test covering accepted and rejected field names.
When it happens
Trigger: Calling Apply with PatchOp{Op:"set_recipients"} where Field is e.g. "To:" (with colon), "recipient", "from", or an empty string.
Common situations: Passing display labels ('To:') instead of the bare field name; using 'from' or 'reply-to' which this op does not support; field values deserialized with surrounding whitespace/casing issues.
Related errors
- recipient address is empty
- draft main body is text/html and text/plain is only its summ
- unsupported body kind %q
- set_calendar: event_start must be a valid ISO 8601 timestamp
- set_calendar: event_end must be a valid ISO 8601 timestamp
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/f1f831c3b266a64e.
Report an issue: GitHub.