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

  1. Use exactly "to", "cc", or "bcc" (case-insensitive; trim whitespace, drop any colon).
  2. If you need to change From/Reply-To, use the dedicated ops or header machinery instead of set_recipients.
  3. 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

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


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