larksuite/cli · error

recipient %q not found in %s

Error message

recipient %q not found in %s

What it means

removeRecipient compares the requested address (case-insensitively, trimmed) against every recipient in the target field. If none matches, the header is left untouched and this error names the address and the header (To/Cc/Bcc) it was not found in.

Source

Thrown at shortcuts/mail/draft/patch.go:221

func removeRecipient(snapshot *DraftSnapshot, field, address string) error {
	field = strings.ToLower(strings.TrimSpace(field))
	addrs, headerName := recipientField(snapshot, field)
	if len(addrs) == 0 {
		return fmt.Errorf("%s header is empty", headerName)
	}
	needle := strings.ToLower(strings.TrimSpace(address))
	next := make([]Address, 0, len(addrs))
	removed := false
	for _, addr := range addrs {
		if strings.EqualFold(strings.TrimSpace(addr.Address), needle) {
			removed = true
			continue
		}
		next = append(next, addr)
	}
	if !removed {
		return fmt.Errorf("recipient %q not found in %s", address, headerName)
	}
	setRecipientField(snapshot, headerName, next)
	return nil
}

func recipientField(snapshot *DraftSnapshot, field string) ([]Address, string) {
	switch field {
	case "to":
		return append([]Address{}, snapshot.To...), "To"
	case "cc":
		return append([]Address{}, snapshot.Cc...), "Cc"
	case "bcc":
		return append([]Address{}, snapshot.Bcc...), "Bcc"
	default:
		return nil, ""
	}
}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Pass the bare email address exactly as stored, not the 'Name <addr>' form
  2. Read the draft's current recipients first and confirm the address and field before removing
  3. Handle the already-removed case as success if removal is idempotent in your workflow

Example fix

// before
removeRecipient(snap, "cc", "Bob <bob@x.com>")
// after
removeRecipient(snap, "cc", "bob@x.com") // bare stored address, case-insensitive
Defensive patterns

Strategy: validation

Validate before calling

needle := strings.ToLower(strings.TrimSpace(address))
found := false
for _, a := range snap.Cc {
    if strings.EqualFold(strings.TrimSpace(a.Address), needle) {
        found = true
        break
    }
}
if !found { /* skip or report */ }

Try / catch

if err := applyOp(op); err != nil && strings.Contains(err.Error(), "not found in") {
    // treat as already-removed, continue
}

Prevention

When it happens

Trigger: A remove_recipient patch op (via applyOp) with an address string that differs from what is stored — wrong case is fine (EqualFold), but extra display-name text, different whitespace, an alias, or a wrong field will not match.

Common situations: Passing 'Bob <bob@x.com>' when only 'bob@x.com' is stored; removing from Cc when the address is in To; the recipient was already removed by a previous op; typo or outdated address from a cached list.

Related errors


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